diff --git a/src/vendor/aliyuncs/oss-sdk-php/CHANGELOG.md b/src/vendor/aliyuncs/oss-sdk-php/CHANGELOG.md index 0de5ae5c7..63167e5f7 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/CHANGELOG.md +++ b/src/vendor/aliyuncs/oss-sdk-php/CHANGELOG.md @@ -1,159 +1,137 @@ -# ChangeLog - Aliyun OSS SDK for PHP - -## v2.7.2 / 2024-10-28 -* Added: presign supports response-* parameters -* Added: forcePathStyle option. - -## v2.7.1 / 2024-02-28 -* Fixed: fix deprecated - -## v2.7.0 / 2024-02-02 -* Added: support signature version 4. -* Added: support checkObjectEndcoding option. -* Added: support strictObjectName option. -* Added: support filePathCompatible option. -* Added: support path style. -* Added: support environment variables credentials provider. -* Update: add filed for some api. -* Fixed: fix some bugs. - -## v2.6.0 / 2022-08-03 -* Added: support credentials provider. -* Fixed: compatible with swoole curl handler. -* Added: support more bucket stat info. - -## v2.5.0 / 2022-05-13 -* Added: support bucket transfer acceleration. -* Added: support bucket cname token. -* Added: support listobjectsV2. - -## v2.4.3 / 2021-08-25 -* Fixed: integer overflow in PHP5.x. - -## v2.4.2 / 2021-06-04 -* Compatible with PHP8. -* Fixed: compatible with PHP5.4. -* Fixed: the signature is incorrect in some scenarios -* Update: change $requestUrl from a member variable to a local variable. - -## v2.4.1 / 2020-09-29 -* Fixed: the getBucketPolicy bug. - - -## v2.4.0 / 2020-08-31 - -* Added: disable Expect: 100-continue -* Added: support getBucketInfo -* Added: support getBucketStat -* Added: support bucket policy -* Added: support bucket encryption -* Added: support bucket tagging -* Added: support bucket worm -* Added: support versioning -* Added: support request payment -* Added: support object tagging -* Added: support code archive -* Added: support process object -* Added: support traffic limit paramter -* Added: support upload object from file handle -* Added: support getSimplifiedObjectMeta -* Fixed: the object name can not be '0' stirng. -* Update: endpoint validity check -* Update: add new pre-signed url api - - -## v2.3.1 / 2019-01-15 - -* translate chinese comments into english -* Added: endpoint validity check - -## v2.3.0 / 2018-01-05 - -* Fixed: putObject support creating empty files -* Fixed: createBucket support IA/Archive -* Added: support restoreObject -* Added: support the Symlink feature -* Added: support getBucketLocation -* Added: support getBucketMeta -* Added: support proxy server Proxy - -## v2.2.4 / 2017-04-25 - -* Fixed getObject to local file bug - -## v2.2.3 / 2017-04-14 - -* Fixed md5 check - -## v2.2.2 / 2017-01-18 - -* Resolve to run the connection number and memory bug on php7 - -## v2.2.1 / 2016-12-01 - -* No HTTP curl is allowed to automatically populate accept-encoding - -## v2.2.0 / 2016-11-22 - -* Fixed PutObject/CompleteMultipartUpload return values(#26) - -## v2.1.0 / 2016-11-12 - -* Added[RTMP](https://help.aliyun.com/document_detail/44297.html)interface -* Add support[image service](https://help.aliyun.com/document_detail/44686.html) - -## v2.0.7 / 2016-06-17 - -* Support append object - -## v2.0.6 - -* Trim access key id/secret and endpoint -* Refine tests and setup travis CI - -## v2.0.5 - -* Added Add/Delete/Get BucketCname interface - -## v2.0.4 - -* Added Put/Get Object Acl interface - -## v2.0.3 - -* Fixing the constants in Util is defined in a PHP version that is less than 5.6. - -## v2.0.2 - -* The problem of content-type cannot be specified when restoring multipart uploads - -## v2.0.1 - -* Increase the ListObjects/ListMultipartUploads special characters -* Provides the interface to get the details of the OssException - - -## 2015.11.25 - -* **Large version upgrade, no longer compatible with previous interface, new version has made great improvements to ease of use, suggesting that users migrate to a new version.** - -## Modify the content - -* PHP 5.2 is no longer supported - -### Add the cotent - -* Introduce namespace -* Interface naming and modification, using hump naming -* The interface is modified, and the common parameters are extracted from the Options parameter. -* The interface returns the result modification, processing the return result, and the user can directly get the data structure easily processed  -* OssClient's constructor changes -* The Endpoint address that support CNAME and IP formats -* Rearrange the sample file organization structure and use function to organize the function points -* Add an interface that sets the connection timeout and requests timeout -* Remove the outdated interface associated with the Object Group -* The message in the OssException is changed to English - -### Repair problem - -* The object name is not complete +# ChangeLog - Aliyun OSS SDK for PHP + +## v2.5.0 / 2022-05-13 +* Added: support bucket transfer acceleration. +* Added: support bucket cname token. +* Added: support listobjectsV2. + +## v2.4.3 / 2021-08-25 +* Fixed: integer overflow in PHP5.x. + +## v2.4.2 / 2021-06-04 +* Compatible with PHP8. +* Fixed: compatible with PHP5.4. +* Fixed: the signature is incorrect in some scenarios +* Update: change $requestUrl from a member variable to a local variable. + +## v2.4.1 / 2020-09-29 +* Fixed: the getBucketPolicy bug. + + +## v2.4.0 / 2020-08-31 + +* Added: disable Expect: 100-continue +* Added: support getBucketInfo +* Added: support getBucketStat +* Added: support bucket policy +* Added: support bucket encryption +* Added: support bucket tagging +* Added: support bucket worm +* Added: support versioning +* Added: support request payment +* Added: support object tagging +* Added: support code archive +* Added: support process object +* Added: support traffic limit paramter +* Added: support upload object from file handle +* Added: support getSimplifiedObjectMeta +* Fixed: the object name can not be '0' stirng. +* Update: endpoint validity check +* Update: add new pre-signed url api + + +## v2.3.1 / 2019-01-15 + +* translate chinese comments into english +* Added: endpoint validity check + +## v2.3.0 / 2018-01-05 + +* Fixed: putObject support creating empty files +* Fixed: createBucket support IA/Archive +* Added: support restoreObject +* Added: support the Symlink feature +* Added: support getBucketLocation +* Added: support getBucketMeta +* Added: support proxy server Proxy + +## v2.2.4 / 2017-04-25 + +* Fixed getObject to local file bug + +## v2.2.3 / 2017-04-14 + +* Fixed md5 check + +## v2.2.2 / 2017-01-18 + +* Resolve to run the connection number and memory bug on php7 + +## v2.2.1 / 2016-12-01 + +* No HTTP curl is allowed to automatically populate accept-encoding + +## v2.2.0 / 2016-11-22 + +* Fixed PutObject/CompleteMultipartUpload return values(#26) + +## v2.1.0 / 2016-11-12 + +* Added[RTMP](https://help.aliyun.com/document_detail/44297.html)interface +* Add support[image service](https://help.aliyun.com/document_detail/44686.html) + +## v2.0.7 / 2016-06-17 + +* Support append object + +## v2.0.6 + +* Trim access key id/secret and endpoint +* Refine tests and setup travis CI + +## v2.0.5 + +* Added Add/Delete/Get BucketCname interface + +## v2.0.4 + +* Added Put/Get Object Acl interface + +## v2.0.3 + +* Fixing the constants in Util is defined in a PHP version that is less than 5.6. + +## v2.0.2 + +* The problem of content-type cannot be specified when restoring multipart uploads + +## v2.0.1 + +* Increase the ListObjects/ListMultipartUploads special characters +* Provides the interface to get the details of the OssException + + +## 2015.11.25 + +* **Large version upgrade, no longer compatible with previous interface, new version has made great improvements to ease of use, suggesting that users migrate to a new version.** + +## Modify the content + +* PHP 5.2 is no longer supported + +### Add the cotent + +* Introduce namespace +* Interface naming and modification, using hump naming +* The interface is modified, and the common parameters are extracted from the Options parameter. +* The interface returns the result modification, processing the return result, and the user can directly get the data structure easily processed  +* OssClient's constructor changes +* The Endpoint address that support CNAME and IP formats +* Rearrange the sample file organization structure and use function to organize the function points +* Add an interface that sets the connection timeout and requests timeout +* Remove the outdated interface associated with the Object Group +* The message in the OssException is changed to English + +### Repair problem + +* The object name is not complete diff --git a/src/vendor/aliyuncs/oss-sdk-php/composer.json b/src/vendor/aliyuncs/oss-sdk-php/composer.json index f8ace5527..29e280b98 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/composer.json +++ b/src/vendor/aliyuncs/oss-sdk-php/composer.json @@ -15,7 +15,7 @@ }, "require-dev" : { "phpunit/phpunit": "*", - "php-coveralls/php-coveralls": "*" + "satooshi/php-coveralls": "*" }, "minimum-stability": "stable", "autoload": { diff --git a/src/vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php b/src/vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php index f5f8f2147..dfa42d323 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php +++ b/src/vendor/aliyuncs/oss-sdk-php/samples/BucketCors.php @@ -26,39 +26,7 @@ Common::println("bucket $bucket corsConfig created:" . $corsConfig->serializeToX // Get cors configuration $corsConfig = $ossClient->getBucketCors($bucket); - -if ($corsConfig->getResponseVary()){ - printf("Response Vary : true" .PHP_EOL); -}else{ - printf("Response Vary : false" .PHP_EOL); -} - -foreach ($corsConfig->getRules() as $key => $rule){ - if($rule->getAllowedHeaders()){ - foreach($rule->getAllowedHeaders() as $header){ - printf("Allowed Headers :" .$header .PHP_EOL); - } - } - if ($rule->getAllowedMethods()){ - foreach($rule->getAllowedMethods() as $method){ - printf("Allowed Methods :" .$method . PHP_EOL); - } - - } - if($rule->getAllowedOrigins()){ - foreach($rule->getAllowedOrigins() as $origin){ - printf("Allowed Origins :" .$origin , PHP_EOL); - } - - } - if($rule->getExposeHeaders()){ - foreach($rule->getExposeHeaders() as $exposeHeader){ - printf("Expose Headers :" .$exposeHeader . PHP_EOL); - } - } - printf("Max Age Seconds :" .$rule->getMaxAgeSeconds() .PHP_EOL); - -} +Common::println("bucket $bucket corsConfig fetched:" . $corsConfig->serializeToXml()); // Delete cors configuration $ossClient->deleteBucketCors($bucket); @@ -110,44 +78,13 @@ function getBucketCors($ossClient, $bucket) $corsConfig = null; try { $corsConfig = $ossClient->getBucketCors($bucket); - - if ($corsConfig->getResponseVary()){ - printf("Response Vary : true" .PHP_EOL); - }else{ - printf("Response Vary : false" .PHP_EOL); - } - foreach ($corsConfig->getRules() as $key => $rule){ - if($rule->getAllowedHeaders()){ - foreach($rule->getAllowedHeaders() as $header){ - printf("Allowed Headers :" .$header .PHP_EOL); - } - } - if ($rule->getAllowedMethods()){ - foreach($rule->getAllowedMethods() as $method){ - printf("Allowed Methods :" .$method . PHP_EOL); - } - - } - if($rule->getAllowedOrigins()){ - foreach($rule->getAllowedOrigins() as $origin){ - printf("Allowed Origins :" .$origin , PHP_EOL); - } - - } - if($rule->getExposeHeaders()){ - foreach($rule->getExposeHeaders() as $exposeHeader){ - printf("Expose Headers :" .$exposeHeader . PHP_EOL); - } - } - printf("Max Age Seconds :" .$rule->getMaxAgeSeconds() .PHP_EOL); - - } } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; } print(__FUNCTION__ . ": OK" . "\n"); + print($corsConfig->serializeToXml() . "\n"); } /** diff --git a/src/vendor/aliyuncs/oss-sdk-php/samples/Object.php b/src/vendor/aliyuncs/oss-sdk-php/samples/Object.php index 5d83efaa7..bf6e86b04 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/samples/Object.php +++ b/src/vendor/aliyuncs/oss-sdk-php/samples/Object.php @@ -55,7 +55,7 @@ $day = 3; $tier = 'Expedited'; $config = new RestoreConfig($day,$tier); $options = array( - OssClient::OSS_RESTORE_CONFIG => $config + OssClient::OSS_RESTORE_CONFIG => $config ); $ossClient->restoreObject($bucket, 'b.file',$options); @@ -93,9 +93,9 @@ $content = "hello world"; // The speed limit is 100 KB/s, which is 819200 bit/s. $options = array( - OssClient::OSS_HEADERS => array( - OssClient::OSS_TRAFFIC_LIMIT => 819200, - )); + OssClient::OSS_HEADERS => array( + OssClient::OSS_TRAFFIC_LIMIT => 819200, + )); // Speed limit upload. $ossClient->putObject($bucket, $object, $content, $options); @@ -205,7 +205,7 @@ function uploadFile($ossClient, $bucket) } /** - * Lists all files and folders in the bucket. + * Lists all files and folders in the bucket. * Note if there's more items than the max-keys specified, the caller needs to use the nextMarker returned as the value for the next call's maker paramter. * Loop through all the items returned from ListObjects. * @@ -227,47 +227,30 @@ function listObjects($ossClient, $bucket) ); try { $listObjectInfo = $ossClient->listObjects($bucket, $options); - printf("Bucket Name: %s". "\n",$listObjectInfo->getBucketName()); - printf("Prefix: %s". "\n",$listObjectInfo->getPrefix()); - printf("Marker: %s". "\n",$listObjectInfo->getMarker()); - printf("Next Marker: %s". "\n",$listObjectInfo->getNextMarker()); - printf("Max Keys: %s". "\n",$listObjectInfo->getMaxKeys()); - printf("Delimiter: %s". "\n",$listObjectInfo->getDelimiter()); - printf("Is Truncated: %s". "\n",$listObjectInfo->getIsTruncated()); - $objectList = $listObjectInfo->getObjectList(); // object list - $prefixList = $listObjectInfo->getPrefixList(); // directory list - if (!empty($objectList)) { - print("objectList:\n"); - foreach ($objectList as $objectInfo) { - printf("Object Name: %s". "\n",$objectInfo->getKey()); - printf("Object Size: %s". "\n",$objectInfo->getSize()); - printf("Object Type: %s". "\n",$objectInfo->getType()); - printf("Object ETag: %s". "\n",$objectInfo->getETag()); - printf("Object Last Modified: %s". "\n",$objectInfo->getLastModified()); - printf("Object Storage Class: %s". "\n",$objectInfo->getStorageClass()); - - if ($objectInfo->getRestoreInfo()){ - printf("Restore Info: %s". "\n",$objectInfo->getRestoreInfo() ); - } - - if($objectInfo->getOwner()){ - printf("Owner Id:".$objectInfo->getOwner()->getId() . "\n"); - printf("Owner Name:".$objectInfo->getOwner()->getDisplayName() . "\n"); - } - } - } - if (!empty($prefixList)) { - print("prefixList: \n"); - foreach ($prefixList as $prefixInfo) { - printf("Common Prefix:%s\n",$prefixInfo->getPrefix()); - } - } } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; } print(__FUNCTION__ . ": OK" . "\n"); + $objectList = $listObjectInfo->getObjectList(); // object list + $prefixList = $listObjectInfo->getPrefixList(); // directory list + if (!empty($objectList)) { + print("objectList:\n"); + foreach ($objectList as $objectInfo) { + print($objectInfo->getKey() . "\n"); + if($objectInfo->getOwner() != null){ + printf("owner id:".$objectInfo->getOwner()->getId() . "\n"); + printf("owner name:".$objectInfo->getOwner()->getDisplayName() . "\n"); + } + } + } + if (!empty($prefixList)) { + print("prefixList: \n"); + foreach ($prefixList as $prefixInfo) { + print($prefixInfo->getPrefix() . "\n"); + } + } } /** @@ -281,61 +264,42 @@ function listObjects($ossClient, $bucket) */ function listObjectsV2($ossClient, $bucket) { - $prefix = 'oss-php-sdk-test/'; - $delimiter = '/'; - $maxkeys = 1000; - $options = array( - 'delimiter' => $delimiter, - 'prefix' => $prefix, - 'max-keys' => $maxkeys, - 'start-after' =>'test-object', - 'fetch-owner' =>'true', - ); - try { - $listObjectInfo = $ossClient->listObjectsV2($bucket, $options); - printf("Bucket Name: %s". "\n",$listObjectInfo->getBucketName()); - printf("Prefix: %s". "\n",$listObjectInfo->getPrefix()); - printf("Next Continuation Token: %s". "\n",$listObjectInfo->getNextContinuationToken()); - printf("Continuation Token: %s". "\n",$listObjectInfo->getContinuationToken()); - printf("Max Keys: %s". "\n",$listObjectInfo->getMaxKeys()); - printf("Key Count: %s". "\n",$listObjectInfo->getKeyCount()); - printf("Delimiter: %s". "\n",$listObjectInfo->getDelimiter()); - printf("Is Truncated: %s". "\n",$listObjectInfo->getIsTruncated()); - printf("Start After: %s". "\n",$listObjectInfo->getStartAfter()); - $objectList = $listObjectInfo->getObjectList(); // object list - $prefixList = $listObjectInfo->getPrefixList(); // directory list - if (!empty($objectList)) { - print("objectList:\n"); - foreach ($objectList as $objectInfo) { - printf("Object Name: %s". "\n",$objectInfo->getKey()); - printf("Object Size: %s". "\n",$objectInfo->getSize()); - printf("Object Type: %s". "\n",$objectInfo->getType()); - printf("Object ETag: %s". "\n",$objectInfo->getETag()); - printf("Object Last Modified: %s". "\n",$objectInfo->getLastModified()); - printf("Object Storage Class: %s". "\n",$objectInfo->getStorageClass()); - - if ($objectInfo->getRestoreInfo()){ - printf("Restore Info: %s". "\n",$objectInfo->getRestoreInfo() ); - } - - if($objectInfo->getOwner()){ - printf("Owner Id:".$objectInfo->getOwner()->getId() . "\n"); - printf("Owner Name:".$objectInfo->getOwner()->getDisplayName() . "\n"); - } - } - } - if (!empty($prefixList)) { - print("prefixList: \n"); - foreach ($prefixList as $prefixInfo) { - printf("Common Prefix:%s\n",$prefixInfo->getPrefix()); - } - } - } catch (OssException $e) { - printf(__FUNCTION__ . ": FAILED\n"); - printf($e->getMessage() . "\n"); - return; - } - print(__FUNCTION__ . ": OK" . "\n"); + $prefix = 'oss-php-sdk-test/'; + $delimiter = '/'; + $maxkeys = 1000; + $options = array( + 'delimiter' => $delimiter, + 'prefix' => $prefix, + 'max-keys' => $maxkeys, + 'start-after' =>'test-object', + 'fetch-owner' =>'true', + ); + try { + $listObjectInfo = $ossClient->listObjectsV2($bucket, $options); + } catch (OssException $e) { + printf(__FUNCTION__ . ": FAILED\n"); + printf($e->getMessage() . "\n"); + return; + } + print(__FUNCTION__ . ": OK" . "\n"); + $objectList = $listObjectInfo->getObjectList(); // object list + $prefixList = $listObjectInfo->getPrefixList(); // directory list + if (!empty($objectList)) { + print("objectList:\n"); + foreach ($objectList as $objectInfo) { + print($objectInfo->getKey() . "\n"); + if($objectInfo->getOwner() != null){ + printf("owner id:".$objectInfo->getOwner()->getId() . "\n"); + printf("owner name:".$objectInfo->getOwner()->getDisplayName() . "\n"); + } + } + } + if (!empty($prefixList)) { + print("prefixList: \n"); + foreach ($prefixList as $prefixInfo) { + print($prefixInfo->getPrefix() . "\n"); + } + } } /** @@ -659,20 +623,20 @@ function doesObjectExist($ossClient, $bucket) */ function putObjectSpeed($ossClient, $bucket) { - $object = "upload-test-object-name.txt"; - $content = file_get_contents(__FILE__); - $options = array( - OssClient::OSS_HEADERS => array( - OssClient::OSS_TRAFFIC_LIMIT => 819200, - )); - try { - $ossClient->putObject($bucket, $object, $content, $options); - } catch (OssException $e) { - printf(__FUNCTION__ . ": FAILED\n"); - printf($e->getMessage() . "\n"); - return; - } - print(__FUNCTION__ . ": OK" . "\n"); + $object = "upload-test-object-name.txt"; + $content = file_get_contents(__FILE__); + $options = array( + OssClient::OSS_HEADERS => array( + OssClient::OSS_TRAFFIC_LIMIT => 819200, + )); + try { + $ossClient->putObject($bucket, $object, $content, $options); + } catch (OssException $e) { + printf(__FUNCTION__ . ": FAILED\n"); + printf($e->getMessage() . "\n"); + return; + } + print(__FUNCTION__ . ": OK" . "\n"); } /** @@ -684,19 +648,19 @@ function putObjectSpeed($ossClient, $bucket) */ function getObjectSpeed($ossClient, $bucket) { - $object = "upload-test-object-name.txt"; - $options = array( - OssClient::OSS_HEADERS => array( - OssClient::OSS_TRAFFIC_LIMIT => 819200, - )); - try { - $ossClient->getObject($bucket, $object, $options); - } catch (OssException $e) { - printf(__FUNCTION__ . ": FAILED\n"); - printf($e->getMessage() . "\n"); - return; - } - print(__FUNCTION__ . ": OK" . "\n"); + $object = "upload-test-object-name.txt"; + $options = array( + OssClient::OSS_HEADERS => array( + OssClient::OSS_TRAFFIC_LIMIT => 819200, + )); + try { + $ossClient->getObject($bucket, $object, $options); + } catch (OssException $e) { + printf(__FUNCTION__ . ": FAILED\n"); + printf($e->getMessage() . "\n"); + return; + } + print(__FUNCTION__ . ": OK" . "\n"); } /** @@ -708,14 +672,14 @@ function getObjectSpeed($ossClient, $bucket) */ function signUrlSpeedUpload($ossClient, $bucket) { - $object = "upload-test-object-name.txt"; - $timeout = 120; - $options = array( - OssClient::OSS_TRAFFIC_LIMIT => 819200, - ); - $timeout = 60; - $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); - print($signedUrl); + $object = "upload-test-object-name.txt"; + $timeout = 120; + $options = array( + OssClient::OSS_TRAFFIC_LIMIT => 819200, + ); + $timeout = 60; + $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); + print($signedUrl); } @@ -728,14 +692,14 @@ function signUrlSpeedUpload($ossClient, $bucket) */ function signUrlSpeedDownload($ossClient, $bucket) { - $object = "upload-test-object-name.txt"; - $timeout = 120; - $options = array( - OssClient::OSS_TRAFFIC_LIMIT => 819200, - ); - $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET", $options); - print($signedUrl); - print(__FUNCTION__ . ": OK" . "\n"); + $object = "upload-test-object-name.txt"; + $timeout = 120; + $options = array( + OssClient::OSS_TRAFFIC_LIMIT => 819200, + ); + $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET", $options); + print($signedUrl); + print(__FUNCTION__ . ": OK" . "\n"); } /** @@ -747,19 +711,19 @@ function signUrlSpeedDownload($ossClient, $bucket) */ function restoreObject($ossClient, $bucket) { - $object = "oss-php-sdk-test/upload-test-object-name.txt"; - $day = 3; - $tier = 'Expedited'; - $config = new RestoreConfig($day,$tier); - $options = array( - OssClient::OSS_RESTORE_CONFIG => $config - ); - try { - $ossClient->restoreObject($bucket, $object,$options); - } catch (OssException $e) { - printf(__FUNCTION__ . ": FAILED\n"); - printf($e->getMessage() . "\n"); - return; - } - print(__FUNCTION__ . ": OK" . "\n"); + $object = "oss-php-sdk-test/upload-test-object-name.txt"; + $day = 3; + $tier = 'Expedited'; + $config = new RestoreConfig($day,$tier); + $options = array( + OssClient::OSS_RESTORE_CONFIG => $config + ); + try { + $ossClient->restoreObject($bucket, $object,$options); + } catch (OssException $e) { + printf(__FUNCTION__ . ": FAILED\n"); + printf($e->getMessage() . "\n"); + return; + } + print(__FUNCTION__ . ": OK" . "\n"); } diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssUtil.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssUtil.php index d2358c2ac..66b467629 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssUtil.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssUtil.php @@ -1,543 +1,534 @@ - $value) { - if (is_string($key) && !is_array($value)) { - if (strlen($value) > 0) { - $temp[] = rawurlencode($key) . '=' . rawurlencode($value); - } else { - $temp[] = rawurlencode($key); - } - } - } - return implode('&', $temp); - } - - /** - * Html encoding '<', '>', '&', '\', '"' in subject parameter. - * - * @param string $subject - * @return string - */ - public static function sReplace($subject) - { - $search = array('<', '>', '&', '\'', '"'); - $replace = array('<', '>', '&', ''', '"'); - return str_replace($search, $replace, $subject); - } - - /** - * Check whether the string includes any chinese character - * - * @param $str - * @return int - */ - public static function chkChinese($str) - { - return preg_match('/[\x80-\xff]./', $str); - } - - /** - * Checks if the string is encoded by GB2312. - * - * @param string $str - * @return boolean false UTF-8 encoding TRUE GB2312 encoding - */ - public static function isGb2312($str) - { - for ($i = 0; $i < strlen($str); $i++) { - $v = ord($str[$i]); - if ($v > 127) { - if (($v >= 228) && ($v <= 233)) { - if (($i + 2) >= (strlen($str) - 1)) return true; // not enough characters - $v1 = ord($str[$i + 1]); - $v2 = ord($str[$i + 2]); - if (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) - return false; - else - return true; - } - } - } - return false; - } - - /** - * Checks if the string is encoded by GBK - * - * @param string $str - * @param boolean $gbk - * @return boolean - */ - public static function checkChar($str, $gbk = true) - { - for ($i = 0; $i < strlen($str); $i++) { - $v = ord($str[$i]); - if ($v > 127) { - if (($v >= 228) && ($v <= 233)) { - if (($i + 2) >= (strlen($str) - 1)) return $gbk ? true : FALSE; // not enough characters - $v1 = ord($str[$i + 1]); - $v2 = ord($str[$i + 2]); - if ($gbk) { - return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? FALSE : TRUE;//GBK - } else { - return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? TRUE : FALSE; - } - } - } - } - return $gbk ? TRUE : FALSE; - } - - /** - * Checks if the bucket name is valid - * bucket naming rules - * 1. Can only include lowercase letters, numbers, or dashes - * 2. Must start and end with lowercase letters or numbers - * 3. Must be within a length from 3 to 63 bytes. - * - * @param string $bucket Bucket name - * @return boolean - */ - public static function validateBucket($bucket) - { - $pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/'; - if (!preg_match($pattern, $bucket)) { - return false; - } - return true; - } - - /** - * Checks if object name is valid - * object naming rules: - * 1. Must be within a length from 1 to 1023 bytes - * 2. Cannot start with '/' or '\\'. - * 3. Must be encoded in UTF-8. - * - * @param string $object Object名称 - * @return boolean - */ - public static function validateObject($object) - { - $pattern = '/^.{1,1023}$/'; - if (!preg_match($pattern, $object) || - self::startsWith($object, '/') || self::startsWith($object, '\\') - ) { - return false; - } - return true; - } - - - /** - * Checks if $str starts with $findMe - * - * @param string $str - * @param string $findMe - * @return bool - */ - public static function startsWith($str, $findMe) - { - if (strpos($str, $findMe) === 0) { - return true; - } else { - return false; - } - } - - - /** - * Generate the xml message of createBucketXmlBody. - * - * @param string $storageClass - * @return string - */ - public static function createBucketXmlBody($storageClass) - { - $xml = new \SimpleXMLElement(''); - $xml->addChild('StorageClass', $storageClass); - return $xml->asXML(); - } - - /** - * validate $options - * - * @param array $options - * @throws OssException - */ - public static function validateOptions($options) - { - //$options - if ($options != NULL && !is_array($options)) { - throw new OssException ($options . ':' . 'option must be array'); - } - } - - /** - * check whether the Content is valid. - * - * @param $content string - * @throws OssException - */ - public static function validateContent($content) - { - if (empty($content)) { - throw new OssException("http body content is invalid"); - } - } - - /** - * Check if BUCKET/OBJECT/OBJECT GROUP is empty. - * - * @param string $name - * @param string $errMsg - * @throws OssException - * @return void - */ - public static function throwOssExceptionWithMessageIfEmpty($name, $errMsg) - { - if (empty($name)) { - if (is_string($name) && $name == '0') - return; - throw new OssException($errMsg); - } - } - - /** - * This is a method for test only. DO NOT USE. - * - * @param $filename - * @param $size - */ - public static function generateFile($filename, $size) - { - if (file_exists($filename) && $size == sprintf('%u',filesize($filename))) { - echo $filename . " already exists, no need to create again. "; - return; - } - $part_size = 1 * 1024 * 1024; - $fp = fopen($filename, "w"); - $characters = << 0) { - if ($size < $part_size) { - $write_size = $size; - } else { - $write_size = $part_size; - } - $size -= $write_size; - $a = $characters[rand(0, $charactersLength - 1)]; - $content = str_repeat($a, $write_size); - $flag = fwrite($fp, $content); - if (!$flag) { - echo "write to " . $filename . " failed.
"; - break; - } - } - } else { - echo "open " . $filename . " failed.
"; - } - fclose($fp); - } - - /** - * Get MD5 of the file. - * - * @param $filename - * @param $from_pos - * @param $to_pos - * @return string - */ - public static function getMd5SumForFile($filename, $from_pos, $to_pos) - { - $content_md5 = ""; - if (($to_pos - $from_pos) > self::OSS_MAX_PART_SIZE) { - return $content_md5; - } - $filesize = sprintf('%u',filesize($filename)); - if ($from_pos >= $filesize || $to_pos >= $filesize || $from_pos < 0 || $to_pos < 0) { - return $content_md5; - } - - $total_length = $to_pos - $from_pos + 1; - $buffer = 8192; - $left_length = $total_length; - if (!file_exists($filename)) { - return $content_md5; - } - - if (false === $fh = fopen($filename, 'rb')) { - return $content_md5; - } - - fseek($fh, $from_pos); - $data = ''; - while (!feof($fh)) { - if ($left_length >= $buffer) { - $read_length = $buffer; - } else { - $read_length = $left_length; - } - if ($read_length <= 0) { - break; - } else { - $data .= fread($fh, $read_length); - $left_length = $left_length - $read_length; - } - } - fclose($fh); - $content_md5 = base64_encode(md5($data, true)); - return $content_md5; - } - - /** - * Check if the OS is Windows. The default encoding in Windows is GBK. - * - * @return bool - */ - public static function isWin() - { - return strtoupper(substr(PHP_OS, 0, 3)) == "WIN"; - } - - /** - * Encodes the file path from GBK to UTF-8. - * The default encoding in Windows is GBK. - * And if the file path is in Chinese, the file would not be found without the transcoding to UTF-8. - * - * @param $file_path - * @return string - */ - public static function encodePath($file_path) - { - if (self::chkChinese($file_path) && self::isWin()) { - $file_path = iconv('utf-8', 'gbk', $file_path); - } - return $file_path; - } - - /** - * Check if the endpoint is in the IPv4 format, such as xxx.xxx.xxx.xxx:port or xxx.xxx.xxx.xxx. - * - * @param string $endpoint The endpoint to check. - * @return boolean - */ - public static function isIPFormat($endpoint) - { - $ip_array = explode(":", $endpoint); - $hostname = $ip_array[0]; - $ret = filter_var($hostname, FILTER_VALIDATE_IP); - if (!$ret) { - return false; - } else { - return true; - } - } - - /** - * Get the host:port from endpoint. - * - * @param string $endpoint the endpoint. - * @return string - * @throws OssException - */ - public static function getHostPortFromEndpoint($endpoint) - { - $str = $endpoint; - $pos = strpos($str, "://"); - if ($pos !== false) { - $str = substr($str, $pos+3); - } - - $pos = strpos($str, '#'); - if ($pos !== false) { - $str = substr($str, 0, $pos); - } - - $pos = strpos($str, '?'); - if ($pos !== false) { - $str = substr($str, 0, $pos); - } - - $pos = strpos($str, '/'); - if ($pos !== false) { - $str = substr($str, 0, $pos); - } - - $pos = strpos($str, '@'); - if ($pos !== false) { - $str = substr($str, $pos+1); - } - - if (!preg_match('/^[\w.-]+(:[0-9]+)?$/', $str)) { - throw new OssException("endpoint is invalid:" . $endpoint); - } - - return $str; - } - - /** - * Generate the xml message of DeleteMultiObjects. - * - * @param string[] $objects - * @param bool $quiet - * @return string - */ - public static function createDeleteObjectsXmlBody($objects, $quiet) - { - $xml = new \SimpleXMLElement(''); - $xml->addChild('Quiet', $quiet); - foreach ($objects as $object) { - $sub_object = $xml->addChild('Object'); - $object = OssUtil::sReplace($object); - $sub_object->addChild('Key', $object); - } - return $xml->asXML(); - } - - /** - * Generate the xml message of DeleteMultiObjects. - * - * @param DeleteObjectInfo[] $objects - * @param bool $quiet - * @return string - */ - public static function createDeleteObjectVersionsXmlBody($objects, $quiet) - { - $xml = new \SimpleXMLElement(''); - $xml->addChild('Quiet', $quiet); - foreach ($objects as $object) { - $sub_object = $xml->addChild('Object'); - $key = OssUtil::sReplace($object->getKey()); - $sub_object->addChild('Key', $key); - $versionId = $object->getVersionId(); - if (!empty($versionId)) { - $sub_object->addChild('VersionId', $object->getVersionId()); - } - } - return $xml->asXML(); - } - - /** - * Generate the xml message of CompleteMultipartUpload. - * - * @param array[] $listParts - * @return string - */ - public static function createCompleteMultipartUploadXmlBody($listParts) - { - $xml = new \SimpleXMLElement(''); - foreach ($listParts as $node) { - $part = $xml->addChild('Part'); - $part->addChild('PartNumber', $node['PartNumber']); - $part->addChild('ETag', $node['ETag']); - } - return $xml->asXML(); - } - - /** - * Read the directory, return a associative array in which the MD5 is the named key and the is the value. - * - * @param string $dir - * @param string $exclude - * @param bool $recursive - * @return string[] - */ - public static function readDir($dir, $exclude = ".|..|.svn|.git", $recursive = false) - { - $file_list_array = array(); - $base_path = $dir; - $exclude_array = explode("|", $exclude); - $exclude_array = array_unique(array_merge($exclude_array, array('.', '..'))); - - if ($recursive) { - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)) as $new_file) { - if ($new_file->isDir()) continue; - $object = str_replace($base_path, '', $new_file); - if (!in_array(strtolower($object), $exclude_array)) { - $object = ltrim($object, '/'); - if (is_file($new_file)) { - $key = md5($new_file . $object, false); - $file_list_array[$key] = array('path' => $new_file, 'file' => $object,); - } - } - } - } else if ($handle = opendir($dir)) { - while (false !== ($file = readdir($handle))) { - if (!in_array(strtolower($file), $exclude_array)) { - $new_file = $dir . '/' . $file; - $object = $file; - $object = ltrim($object, '/'); - if (is_file($new_file)) { - $key = md5($new_file . $object, false); - $file_list_array[$key] = array('path' => $new_file, 'file' => $object,); - } - } - } - closedir($handle); - } - return $file_list_array; - } - - /** - * Decode key based on the encoding type - * - * @param string $key - * @param string $encoding - * @return string - */ - public static function decodeKey($key, $encoding) - { - if ($encoding == "") { - return $key; - } - - if ($encoding == "url") { - return rawurldecode($key); - } else { - throw new OssException("Unrecognized encoding type: " . $encoding); - } - } - - public static function unparseUrl($parsed_url) { - $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; - $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; - $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; - return "$scheme$host$port$path$query"; - } -} + $value) { + if (is_string($key) && !is_array($value)) { + if (strlen($value) > 0) { + $temp[] = rawurlencode($key) . '=' . rawurlencode($value); + } else { + $temp[] = rawurlencode($key); + } + } + } + return implode('&', $temp); + } + + /** + * Html encoding '<', '>', '&', '\', '"' in subject parameter. + * + * @param string $subject + * @return string + */ + public static function sReplace($subject) + { + $search = array('<', '>', '&', '\'', '"'); + $replace = array('<', '>', '&', ''', '"'); + return str_replace($search, $replace, $subject); + } + + /** + * Check whether the string includes any chinese character + * + * @param $str + * @return int + */ + public static function chkChinese($str) + { + return preg_match('/[\x80-\xff]./', $str); + } + + /** + * Checks if the string is encoded by GB2312. + * + * @param string $str + * @return boolean false UTF-8 encoding TRUE GB2312 encoding + */ + public static function isGb2312($str) + { + for ($i = 0; $i < strlen($str); $i++) { + $v = ord($str[$i]); + if ($v > 127) { + if (($v >= 228) && ($v <= 233)) { + if (($i + 2) >= (strlen($str) - 1)) return true; // not enough characters + $v1 = ord($str[$i + 1]); + $v2 = ord($str[$i + 2]); + if (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) + return false; + else + return true; + } + } + } + return false; + } + + /** + * Checks if the string is encoded by GBK + * + * @param string $str + * @param boolean $gbk + * @return boolean + */ + public static function checkChar($str, $gbk = true) + { + for ($i = 0; $i < strlen($str); $i++) { + $v = ord($str[$i]); + if ($v > 127) { + if (($v >= 228) && ($v <= 233)) { + if (($i + 2) >= (strlen($str) - 1)) return $gbk ? true : FALSE; // not enough characters + $v1 = ord($str[$i + 1]); + $v2 = ord($str[$i + 2]); + if ($gbk) { + return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? FALSE : TRUE;//GBK + } else { + return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? TRUE : FALSE; + } + } + } + } + return $gbk ? TRUE : FALSE; + } + + /** + * Checks if the bucket name is valid + * bucket naming rules + * 1. Can only include lowercase letters, numbers, or dashes + * 2. Must start and end with lowercase letters or numbers + * 3. Must be within a length from 3 to 63 bytes. + * + * @param string $bucket Bucket name + * @return boolean + */ + public static function validateBucket($bucket) + { + $pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/'; + if (!preg_match($pattern, $bucket)) { + return false; + } + return true; + } + + /** + * Checks if object name is valid + * object naming rules: + * 1. Must be within a length from 1 to 1023 bytes + * 2. Cannot start with '/' or '\\'. + * 3. Must be encoded in UTF-8. + * + * @param string $object Object名称 + * @return boolean + */ + public static function validateObject($object) + { + $pattern = '/^.{1,1023}$/'; + if (!preg_match($pattern, $object) || + self::startsWith($object, '/') || self::startsWith($object, '\\') + ) { + return false; + } + return true; + } + + + /** + * Checks if $str starts with $findMe + * + * @param string $str + * @param string $findMe + * @return bool + */ + public static function startsWith($str, $findMe) + { + if (strpos($str, $findMe) === 0) { + return true; + } else { + return false; + } + } + + + /** + * Generate the xml message of createBucketXmlBody. + * + * @param string $storageClass + * @return string + */ + public static function createBucketXmlBody($storageClass) + { + $xml = new \SimpleXMLElement(''); + $xml->addChild('StorageClass', $storageClass); + return $xml->asXML(); + } + + /** + * validate $options + * + * @param array $options + * @throws OssException + * @return boolean + */ + public static function validateOptions($options) + { + //$options + if ($options != NULL && !is_array($options)) { + throw new OssException ($options . ':' . 'option must be array'); + } + } + + /** + * check whether the Content is valid. + * + * @param $content string + * @throws OssException + */ + public static function validateContent($content) + { + if (empty($content)) { + throw new OssException("http body content is invalid"); + } + } + + /** + * Check if BUCKET/OBJECT/OBJECT GROUP is empty. + * + * @param string $name + * @param string $errMsg + * @throws OssException + * @return void + */ + public static function throwOssExceptionWithMessageIfEmpty($name, $errMsg) + { + if (empty($name)) { + if (is_string($name) && $name == '0') + return; + throw new OssException($errMsg); + } + } + + /** + * This is a method for test only. DO NOT USE. + * + * @param $filename + * @param $size + */ + public static function generateFile($filename, $size) + { + if (file_exists($filename) && $size == sprintf('%u',filesize($filename))) { + echo $filename . " already exists, no need to create again. "; + return; + } + $part_size = 1 * 1024 * 1024; + $fp = fopen($filename, "w"); + $characters = << 0) { + if ($size < $part_size) { + $write_size = $size; + } else { + $write_size = $part_size; + } + $size -= $write_size; + $a = $characters[rand(0, $charactersLength - 1)]; + $content = str_repeat($a, $write_size); + $flag = fwrite($fp, $content); + if (!$flag) { + echo "write to " . $filename . " failed.
"; + break; + } + } + } else { + echo "open " . $filename . " failed.
"; + } + fclose($fp); + } + + /** + * Get MD5 of the file. + * + * @param $filename + * @param $from_pos + * @param $to_pos + * @return string + */ + public static function getMd5SumForFile($filename, $from_pos, $to_pos) + { + $content_md5 = ""; + if (($to_pos - $from_pos) > self::OSS_MAX_PART_SIZE) { + return $content_md5; + } + $filesize = sprintf('%u',filesize($filename)); + if ($from_pos >= $filesize || $to_pos >= $filesize || $from_pos < 0 || $to_pos < 0) { + return $content_md5; + } + + $total_length = $to_pos - $from_pos + 1; + $buffer = 8192; + $left_length = $total_length; + if (!file_exists($filename)) { + return $content_md5; + } + + if (false === $fh = fopen($filename, 'rb')) { + return $content_md5; + } + + fseek($fh, $from_pos); + $data = ''; + while (!feof($fh)) { + if ($left_length >= $buffer) { + $read_length = $buffer; + } else { + $read_length = $left_length; + } + if ($read_length <= 0) { + break; + } else { + $data .= fread($fh, $read_length); + $left_length = $left_length - $read_length; + } + } + fclose($fh); + $content_md5 = base64_encode(md5($data, true)); + return $content_md5; + } + + /** + * Check if the OS is Windows. The default encoding in Windows is GBK. + * + * @return bool + */ + public static function isWin() + { + return strtoupper(substr(PHP_OS, 0, 3)) == "WIN"; + } + + /** + * Encodes the file path from GBK to UTF-8. + * The default encoding in Windows is GBK. + * And if the file path is in Chinese, the file would not be found without the transcoding to UTF-8. + * + * @param $file_path + * @return string + */ + public static function encodePath($file_path) + { + if (self::chkChinese($file_path) && self::isWin()) { + $file_path = iconv('utf-8', 'gbk', $file_path); + } + return $file_path; + } + + /** + * Check if the endpoint is in the IPv4 format, such as xxx.xxx.xxx.xxx:port or xxx.xxx.xxx.xxx. + * + * @param string $endpoint The endpoint to check. + * @return boolean + */ + public static function isIPFormat($endpoint) + { + $ip_array = explode(":", $endpoint); + $hostname = $ip_array[0]; + $ret = filter_var($hostname, FILTER_VALIDATE_IP); + if (!$ret) { + return false; + } else { + return true; + } + } + + /** + * Get the host:port from endpoint. + * + * @param string $endpoint the endpoint. + * @return boolean + */ + public static function getHostPortFromEndpoint($endpoint) + { + $str = $endpoint; + $pos = strpos($str, "://"); + if ($pos !== false) { + $str = substr($str, $pos+3); + } + + $pos = strpos($str, '#'); + if ($pos !== false) { + $str = substr($str, 0, $pos); + } + + $pos = strpos($str, '?'); + if ($pos !== false) { + $str = substr($str, 0, $pos); + } + + $pos = strpos($str, '/'); + if ($pos !== false) { + $str = substr($str, 0, $pos); + } + + $pos = strpos($str, '@'); + if ($pos !== false) { + $str = substr($str, $pos+1); + } + + if (!preg_match('/^[\w.-]+(:[0-9]+)?$/', $str)) { + throw new OssException("endpoint is invalid:" . $endpoint); + } + + return $str; + } + + /** + * Generate the xml message of DeleteMultiObjects. + * + * @param string[] $objects + * @param bool $quiet + * @return string + */ + public static function createDeleteObjectsXmlBody($objects, $quiet) + { + $xml = new \SimpleXMLElement(''); + $xml->addChild('Quiet', $quiet); + foreach ($objects as $object) { + $sub_object = $xml->addChild('Object'); + $object = OssUtil::sReplace($object); + $sub_object->addChild('Key', $object); + } + return $xml->asXML(); + } + + /** + * Generate the xml message of DeleteMultiObjects. + * + * @param DeleteObjectInfo[] $objects + * @param bool $quiet + * @return string + */ + public static function createDeleteObjectVersionsXmlBody($objects, $quiet) + { + $xml = new \SimpleXMLElement(''); + $xml->addChild('Quiet', $quiet); + foreach ($objects as $object) { + $sub_object = $xml->addChild('Object'); + $key = OssUtil::sReplace($object->getKey()); + $sub_object->addChild('Key', $key); + $versionId = $object->getVersionId(); + if (!empty($versionId)) { + $sub_object->addChild('VersionId', $object->getVersionId()); + } + } + return $xml->asXML(); + } + + /** + * Generate the xml message of CompleteMultipartUpload. + * + * @param array[] $listParts + * @return string + */ + public static function createCompleteMultipartUploadXmlBody($listParts) + { + $xml = new \SimpleXMLElement(''); + foreach ($listParts as $node) { + $part = $xml->addChild('Part'); + $part->addChild('PartNumber', $node['PartNumber']); + $part->addChild('ETag', $node['ETag']); + } + return $xml->asXML(); + } + + /** + * Read the directory, return a associative array in which the MD5 is the named key and the is the value. + * + * @param string $dir + * @param string $exclude + * @param bool $recursive + * @return string[] + */ + public static function readDir($dir, $exclude = ".|..|.svn|.git", $recursive = false) + { + $file_list_array = array(); + $base_path = $dir; + $exclude_array = explode("|", $exclude); + $exclude_array = array_unique(array_merge($exclude_array, array('.', '..'))); + + if ($recursive) { + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)) as $new_file) { + if ($new_file->isDir()) continue; + $object = str_replace($base_path, '', $new_file); + if (!in_array(strtolower($object), $exclude_array)) { + $object = ltrim($object, '/'); + if (is_file($new_file)) { + $key = md5($new_file . $object, false); + $file_list_array[$key] = array('path' => $new_file, 'file' => $object,); + } + } + } + } else if ($handle = opendir($dir)) { + while (false !== ($file = readdir($handle))) { + if (!in_array(strtolower($file), $exclude_array)) { + $new_file = $dir . '/' . $file; + $object = $file; + $object = ltrim($object, '/'); + if (is_file($new_file)) { + $key = md5($new_file . $object, false); + $file_list_array[$key] = array('path' => $new_file, 'file' => $object,); + } + } + } + closedir($handle); + } + return $file_list_array; + } + + /** + * Decode key based on the encoding type + * + * @param string $key + * @param string $encoding + * @return string + */ + public static function decodeKey($key, $encoding) + { + if ($encoding == "") { + return $key; + } + + if ($encoding == "url") { + return rawurldecode($key); + } else { + throw new OssException("Unrecognized encoding type: " . $encoding); + } + } +} diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Http/RequestCore.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Http/RequestCore.php index 58bb21506..c8089b419 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Http/RequestCore.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Http/RequestCore.php @@ -170,7 +170,7 @@ class RequestCore public $registered_streaming_write_callback = null; /** - * The request timeout time, which is 5,184,000 seconds,that is, 60 days by default + * The request timeout time, which is 5,184,000 seconds,that is, 6 days by default * * @var int */ @@ -789,7 +789,7 @@ class RequestCore } // As long as this came back as a valid resource or CurlHandle instance... - if (is_resource($curl_handle) || (is_object($curl_handle) && in_array(get_class($curl_handle),array('CurlHandle','Swoole\Curl\Handler', 'Swoole\Coroutine\Curl\Handle'),true))) { + if (is_resource($curl_handle) || (is_object($curl_handle) && get_class($curl_handle) === 'CurlHandle')) { // Determine what's what. $header_size = curl_getinfo($curl_handle, CURLINFO_HEADER_SIZE); $this->response_headers = substr($this->response, 0, $header_size); diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/BucketStat.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/BucketStat.php index 60c7e55c8..9e2989a76 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/BucketStat.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/BucketStat.php @@ -41,135 +41,6 @@ class BucketStat return $this->multipartUploadCount; } - /** - * Get live channel count - * - * @return int - */ - public function getLiveChannelCount() - { - return $this->liveChannelCount; - } - - /** - * Get last modified time - * - * @return int - */ - public function getLastModifiedTime() - { - return $this->lastModifiedTime; - } - - /** - * Get standard storage - * - * @return int - */ - public function getStandardStorage() - { - return $this->standardStorage; - } - - /** - * Get standard object count - * - * @return int - */ - public function getStandardObjectCount() - { - return $this->standardObjectCount; - } - - /** - * Get infrequent access storage - * - * @return int - */ - public function getInfrequentAccessStorage() - { - return $this->infrequentAccessStorage; - } - - /** - * Get infrequent access real storage - * - * @return int - */ - public function getInfrequentAccessRealStorage() - { - return $this->infrequentAccessRealStorage; - } - - /** - * Get infrequent access object count - * - * @return int - */ - public function getInfrequentAccessObjectCount() - { - return $this->infrequentAccessObjectCount; - } - - /** - * Get archive storage - * - * @return int - */ - public function getArchiveStorage() - { - return $this->archiveStorage; - } - - /** - * Get archive real storage - * - * @return int - */ - public function getArchiveRealStorage() - { - return $this->archiveRealStorage; - } - /** - * Get archive object count - * - * @return int - */ - public function getArchiveObjectCount() - { - return $this->archiveObjectCount; - } - - /** - * Get cold archive storage - * - * @return int - */ - public function getColdArchiveStorage() - { - return $this->coldArchiveStorage; - } - - /** - * Get cold archive real storage - * - * @return int - */ - public function getColdArchiveRealStorage() - { - return $this->coldArchiveRealStorage; - } - - /** - * Get cold archive object count - * - * @return int - */ - public function getColdArchiveObjectCount() - { - return $this->coldArchiveObjectCount; - } - /** * Parse stat from the xml. * @@ -189,45 +60,6 @@ class BucketStat if (isset($xml->MultipartUploadCount) ) { $this->multipartUploadCount = intval($xml->MultipartUploadCount); } - if (isset($xml->LiveChannelCount) ) { - $this->liveChannelCount = intval($xml->LiveChannelCount); - } - if (isset($xml->LastModifiedTime) ) { - $this->lastModifiedTime = intval($xml->LastModifiedTime); - } - if (isset($xml->StandardStorage) ) { - $this->standardStorage = intval($xml->StandardStorage); - } - if (isset($xml->StandardObjectCount) ) { - $this->standardObjectCount = intval($xml->StandardObjectCount); - } - if (isset($xml->InfrequentAccessStorage) ) { - $this->infrequentAccessStorage = intval($xml->InfrequentAccessStorage); - } - if (isset($xml->InfrequentAccessRealStorage) ) { - $this->infrequentAccessRealStorage = intval($xml->InfrequentAccessRealStorage); - } - if (isset($xml->InfrequentAccessObjectCount) ) { - $this->infrequentAccessObjectCount = intval($xml->InfrequentAccessObjectCount); - } - if (isset($xml->ArchiveStorage) ) { - $this->archiveStorage = intval($xml->ArchiveStorage); - } - if (isset($xml->ArchiveRealStorage) ) { - $this->archiveRealStorage = intval($xml->ArchiveRealStorage); - } - if (isset($xml->ArchiveObjectCount) ) { - $this->archiveObjectCount = intval($xml->ArchiveObjectCount); - } - if (isset($xml->ColdArchiveStorage) ) { - $this->coldArchiveStorage = intval($xml->ColdArchiveStorage); - } - if (isset($xml->ColdArchiveRealStorage) ) { - $this->coldArchiveRealStorage = intval($xml->ColdArchiveRealStorage); - } - if (isset($xml->ColdArchiveObjectCount) ) { - $this->coldArchiveObjectCount = intval($xml->ColdArchiveObjectCount); - } } /** @@ -250,82 +82,4 @@ class BucketStat */ private $multipartUploadCount; - /** - * live channel count - * @var int - */ - private $liveChannelCount; - - /** - * last modified time - * @var int - */ - private $lastModifiedTime; - - /** - * standard storage - * @var int - */ - private $standardStorage; - - /** - * standard object count - * @var int - */ - private $standardObjectCount; - - /** - * infrequent access storage - * @var int - */ - private $infrequentAccessStorage; - - /** - * infrequent access real storage - * @var int - */ - private $infrequentAccessRealStorage; - - /** - * infrequent access object Count - * @var int - */ - private $infrequentAccessObjectCount; - - /** - * archive storage - * @var int - */ - private $archiveStorage; - - /** - * archive real storage - * @var int - */ - private $archiveRealStorage; - - /** - * archive object count - * @var int - */ - private $archiveObjectCount; - - /** - * cold archive storage - * @var int - */ - private $coldArchiveStorage; - - /** - * cold archive real storage - * @var int - */ - private $coldArchiveRealStorage; - - /** - * cold archive object count - * @var int - */ - private $coldArchiveObjectCount; - } \ No newline at end of file diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/CorsConfig.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/CorsConfig.php index e0f18923f..62a0d7103 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/CorsConfig.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/CorsConfig.php @@ -45,26 +45,10 @@ class CorsConfig implements XmlConfig } $this->rules[] = $rule; } - /** - * @param boolean $value - */ - public function setResponseVary($value) - { - $this->responseVary = $value; - } - - /** - * @return boolean - */ - public function getResponseVary(){ - if (isset($this->responseVary)) { - return $this->responseVary; - } - return false; - } /** * Parse CorsConfig from the xml. + * * @param string $strXml * @throws OssException * @return null @@ -72,10 +56,6 @@ class CorsConfig implements XmlConfig public function parseFromXml($strXml) { $xml = simplexml_load_string($strXml); - if(isset($xml->ResponseVary)){ - $this->responseVary = - (strval($xml->ResponseVary) === 'TRUE' || strval($xml->ResponseVary) === 'true') ? true : false; - } if (!isset($xml->CORSRule)) return; foreach ($xml->CORSRule as $rule) { $corsRule = new CorsRule(); @@ -94,6 +74,7 @@ class CorsConfig implements XmlConfig } $this->addRule($corsRule); } + return; } /** @@ -108,13 +89,6 @@ class CorsConfig implements XmlConfig $xmlRule = $xml->addChild('CORSRule'); $rule->appendToXml($xmlRule); } - if(isset($this->responseVary)){ - if ($this->responseVary) { - $xml->addChild('ResponseVary', 'true'); - } else { - $xml->addChild('ResponseVary', 'false'); - } - } return $xml->asXML(); } @@ -136,5 +110,4 @@ class CorsConfig implements XmlConfig * @var CorsRule[] */ private $rules = array(); - private $responseVary; } \ No newline at end of file diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectInfo.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectInfo.php index 9e538bf2a..5b412240d 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectInfo.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectInfo.php @@ -24,10 +24,8 @@ class ObjectInfo * @param string $type * @param string $size * @param string $storageClass - * @param Owner|null $owner - * @param null $restoreInfo */ - public function __construct($key, $lastModified, $eTag, $type, $size, $storageClass,$owner=null,$restoreInfo=null) + public function __construct($key, $lastModified, $eTag, $type, $size, $storageClass) { $this->key = $key; $this->lastModified = $lastModified; @@ -35,8 +33,6 @@ class ObjectInfo $this->type = $type; $this->size = $size; $this->storageClass = $storageClass; - $this->owner = $owner; - $this->restoreInfo = $restoreInfo; } /** @@ -98,32 +94,10 @@ class ObjectInfo return $this->storageClass; } - /** - * @return string - */ - public function getRestoreInfo() - { - return $this->restoreInfo; - } - - - /** - * @return Owner|null - */ - public function getOwner() - { - return $this->owner; - } - private $key = ""; private $lastModified = ""; private $eTag = ""; private $type = ""; private $size = "0"; private $storageClass = ""; - /** - * @var Owner - */ - private $owner; - private $restoreInfo; } \ No newline at end of file diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectVersionListInfo.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectVersionListInfo.php index f976b7e60..c94210d01 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectVersionListInfo.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Model/ObjectVersionListInfo.php @@ -22,7 +22,7 @@ class ObjectVersionListInfo * @param string $nextVersionIdMarker * @param string $maxKeys * @param string $delimiter - * @param null|string $isTruncated + * @param null $isTruncated * @param array $objectversionList * @param array $deleteMarkerList * @param array $prefixList @@ -151,7 +151,7 @@ class ObjectVersionListInfo private $prefix = ""; private $keyMarker = ""; private $nextKeyMarker = ""; - private $versionIdMarker = ""; + private $versionIdmarker = ""; private $nextVersionIdMarker = ""; private $maxKeys = 0; private $delimiter = ""; diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php index ab6b7fd30..d7f73df9a 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php @@ -1,21 +1,13 @@ $endpoint, - 'cname' => $isCName, - 'request_proxy' => $requestProxy, - 'provider' => $provider - ); - $this->__initNewClient($config); - } - - /** - * @param array $config - * @throws OssException - */ - private function __initNewClient($config = array()) - { - $isCName = isset($config['cname']) ? $config['cname'] : false; - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : ''; - $requestProxy = isset($config['request_proxy']) ? $config['request_proxy'] : null; - $provider = isset($config['provider']) ? $config['provider'] : ''; if (empty($endpoint)) { throw new OssException("endpoint is empty"); } $this->hostname = $this->checkEndpoint($endpoint, $isCName); - if (isset($config['forcePathStyle'])) { - if ($config['forcePathStyle'] === true) { - $this->hostType = self::OSS_HOST_TYPE_PATH_STYLE; - } - } + $this->accessKeyId = $accessKeyId; + $this->accessKeySecret = $accessKeySecret; + $this->securityToken = $securityToken; $this->requestProxy = $requestProxy; - if (!$provider instanceof CredentialsProvider) { - throw new OssException("provider must be an instance of CredentialsProvider"); - } - $this->provider = $provider; - - $this->region = isset($config['region']) ? $config['region'] : ''; - $this->cloudBoxId = isset($config['cloudBoxId']) ? $config['cloudBoxId'] : ''; - - // $enableStrictObjName - $this->enableStrictObjName = true; - if (isset($config['strictObjectName'])) { - if ($config['strictObjectName'] === false) { - $this->enableStrictObjName = false; - } - } - - // sign version - $signatureVersion = self::OSS_SIGNATURE_VERSION_V1; - if (isset($config['signatureVersion']) && $config['signatureVersion'] === self::OSS_SIGNATURE_VERSION_V4) { - $signatureVersion = self::OSS_SIGNATURE_VERSION_V4; - } - if ($signatureVersion === self::OSS_SIGNATURE_VERSION_V4) { - $this->enableStrictObjName = false; - $this->signer = new SignerV4(); - } else { - $this->signer = new SignerV1(); - } - - //checkObjectEncoding - $this->checkObjectEncoding = false; - if (isset($config['checkObjectEncoding'])) { - if ($config['checkObjectEncoding'] === true) { - $this->checkObjectEncoding = true; - } - } - - //filePathCompatible - $this->filePathCompatible = false; - if (version_compare(phpversion(), '7.0.0', '<')) { - if (OssUtil::isWin()) { - $this->filePathCompatible = true; - } - } - if (isset($config['filePathCompatible'])) { - if ($config['filePathCompatible'] === true) { - $this->filePathCompatible = true; - } else if ($config['filePathCompatible'] === false) { - $this->filePathCompatible = false; - } - } - self::checkEnv(); } @@ -233,8 +135,8 @@ class OssClient * Lists the Bucket [GetService]. Not applicable if the endpoint is CName (because CName must be binded to a specific bucket). * * @param array $options - * @return BucketListInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return BucketListInfo */ public function listBuckets($options = NULL) { @@ -244,6 +146,7 @@ class OssClient $this->precheckOptions($options); $options[self::OSS_BUCKET] = ''; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $response = $this->auth($options); $result = new ListBucketsResult($response); return $result->getData(); @@ -255,15 +158,16 @@ class OssClient * @param string $bucket * @param string $acl * @param array $options + * @param string $storageType * @return null - * @throws OssException|RequestCore_Exception */ public function createBucket($bucket, $acl = self::OSS_ACL_TYPE_PRIVATE, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; - $options[self::OSS_HEADERS][self::OSS_ACL] = $acl; + $options[self::OSS_OBJECT] = '/'; + $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl); if (isset($options[self::OSS_STORAGE])) { $this->precheckStorage($options[self::OSS_STORAGE]); $options[self::OSS_CONTENT] = OssUtil::createBucketXmlBody($options[self::OSS_STORAGE]); @@ -282,13 +186,13 @@ class OssClient * @param string $bucket * @param array $options * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucket($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); return $result->getData(); @@ -298,14 +202,15 @@ class OssClient * Checks if a bucket exists * * @param string $bucket - * @return bool|null - * @throws OssException|RequestCore_Exception + * @return bool + * @throws OssException */ public function doesBucketExist($bucket) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'acl'; $response = $this->auth($options); $result = new ExistResult($response); @@ -317,14 +222,15 @@ class OssClient * * @param string $bucket * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getBucketLocation($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'location'; $response = $this->auth($options); $result = new GetLocationResult($response); @@ -335,15 +241,15 @@ class OssClient * Get the Meta information for the Bucket * * @param string $bucket - * @param array $options Refer to the SDK documentation - * @return array|null - * @throws OssException|RequestCore_Exception + * @param array $options Refer to the SDK documentation + * @return array */ public function getBucketMeta($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD; + $options[self::OSS_OBJECT] = '/'; $response = $this->auth($options); $result = new HeaderResult($response); return $result->getData(); @@ -354,14 +260,15 @@ class OssClient * * @param string $bucket * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getBucketAcl($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'acl'; $response = $this->auth($options); $result = new AclResult($response); @@ -374,15 +281,16 @@ class OssClient * @param string $bucket bucket name * @param string $acl access permissions, valid values are ['private', 'public-read', 'public-read-write'] * @param array $options by default is empty + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putBucketAcl($bucket, $acl, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; - $options[self::OSS_HEADERS][self::OSS_ACL] = $acl; + $options[self::OSS_OBJECT] = '/'; + $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl); $options[self::OSS_SUB_RESOURCE] = 'acl'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -395,8 +303,8 @@ class OssClient * @param string $bucket * @param string $object * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getObjectAcl($bucket, $object, $options = NULL) { @@ -417,8 +325,8 @@ class OssClient * @param string $object object name * @param string $acl access permissions, valid values are ['default', 'private', 'public-read', 'public-read-write'] * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putObjectAcl($bucket, $object, $acl, $options = NULL) { @@ -426,7 +334,7 @@ class OssClient $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; $options[self::OSS_OBJECT] = $object; - $options[self::OSS_HEADERS][self::OSS_OBJECT_ACL] = $acl; + $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_ACL => $acl); $options[self::OSS_SUB_RESOURCE] = 'acl'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -438,14 +346,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options by default is empty - * @return LoggingConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return LoggingConfig */ public function getBucketLogging($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'logging'; $response = $this->auth($options); $result = new GetLoggingResult($response); @@ -459,8 +368,8 @@ class OssClient * @param string $targetBucket The logging file's bucket * @param string $targetPrefix The logging file's prefix * @param array $options By default is empty. + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putBucketLogging($bucket, $targetBucket, $targetPrefix, $options = NULL) { @@ -468,6 +377,7 @@ class OssClient $this->precheckBucket($targetBucket, 'targetbucket is not allowed empty'); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'logging'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; @@ -483,14 +393,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucketLogging($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'logging'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -503,14 +414,15 @@ class OssClient * @param string $bucket bucket name * @param WebsiteConfig $websiteConfig * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putBucketWebsite($bucket, $websiteConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'website'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $websiteConfig->serializeToXml(); @@ -524,14 +436,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return WebsiteConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return WebsiteConfig */ public function getBucketWebsite($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'website'; $response = $this->auth($options); $result = new GetWebsiteResult($response); @@ -543,14 +456,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucketWebsite($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'website'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -563,14 +477,15 @@ class OssClient * @param string $bucket bucket name * @param CorsConfig $corsConfig CORS config. Check out the details from OSS API document * @param array $options array + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putBucketCors($bucket, $corsConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'cors'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $corsConfig->serializeToXml(); @@ -584,17 +499,18 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return CorsConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return CorsConfig */ public function getBucketCors($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'cors'; $response = $this->auth($options); - $result = new GetCorsResult($response); + $result = new GetCorsResult($response, __FUNCTION__); return $result->getData(); } @@ -603,14 +519,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucketCors($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'cors'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -623,14 +540,15 @@ class OssClient * @param string $bucket bucket name * @param string $cname * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function addBucketCname($bucket, $cname, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_POST; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $cnameConfig = new CnameConfig(); $cnameConfig->addCname($cname); @@ -648,14 +566,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return CnameConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return CnameConfig */ public function getBucketCname($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_CNAME] = ''; $response = $this->auth($options); $result = new GetCnameResult($response); @@ -666,16 +585,17 @@ class OssClient * Remove a CName binding from the bucket * * @param string $bucket bucket name - * @param CnameConfig $cname + * @param CnameConfig $cnameConfig * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucketCname($bucket, $cname, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_POST; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $cnameConfig = new CnameConfig(); $cnameConfig->addCname($cname); @@ -693,14 +613,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return CnameTokenInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return CnameToken */ public function createBucketCnameToken($bucket, $cname, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_POST; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $cnameConfig = new CnameConfig(); $cnameConfig->addCname($cname); @@ -717,14 +638,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return CnameTokenInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return CnameToken */ public function getBucketCnameToken($bucket, $cname, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_COMP] = 'token'; $options[self::OSS_CNAME] = $cname; $response = $this->auth($options); @@ -739,8 +661,8 @@ class OssClient * @param string channelName $channelName * @param LiveChannelConfig $channelConfig * @param array $options - * @return LiveChannelInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return LiveChannelInfo */ public function putBucketLiveChannel($bucket, $channelName, $channelConfig, $options = NULL) { @@ -757,7 +679,7 @@ class OssClient $info = $result->getData(); $info->setName($channelName); $info->setDescription($channelConfig->getDescription()); - + return $info; } @@ -768,8 +690,8 @@ class OssClient * @param string channelName $channelName * @param string channelStatus $channelStatus enabled or disabled * @param array $options - * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function putLiveChannelStatus($bucket, $channelName, $channelStatus, $options = NULL) { @@ -791,8 +713,8 @@ class OssClient * @param string $bucket bucket name * @param string channelName $channelName * @param array $options - * @return GetLiveChannelInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return GetLiveChannelInfo */ public function getLiveChannelInfo($bucket, $channelName, $options = NULL) { @@ -813,8 +735,8 @@ class OssClient * @param string $bucket bucket name * @param string channelName $channelName * @param array $options - * @return GetLiveChannelStatus|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return GetLiveChannelStatus */ public function getLiveChannelStatus($bucket, $channelName, $options = NULL) { @@ -824,20 +746,20 @@ class OssClient $options[self::OSS_OBJECT] = $channelName; $options[self::OSS_SUB_RESOURCE] = 'live'; $options[self::OSS_COMP] = 'stat'; - + $response = $this->auth($options); $result = new GetLiveChannelStatusResult($response); return $result->getData(); } - /** + /** * Gets the LiveChannel pushing streaming record * * @param string $bucket bucket name * @param string channelName $channelName * @param array $options - * @return GetLiveChannelHistory|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return GetLiveChannelHistory */ public function getLiveChannelHistory($bucket, $channelName, $options = NULL) { @@ -852,20 +774,21 @@ class OssClient $result = new GetLiveChannelHistoryResult($response); return $result->getData(); } - + /** *Gets the live channel list under a bucket. * * @param string $bucket bucket name * @param array $options - * @return LiveChannelListInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return LiveChannelListInfo */ public function listBucketLiveChannels($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'live'; $options[self::OSS_QUERY_STRING] = array( 'prefix' => isset($options['prefix']) ? $options['prefix'] : '', @@ -884,11 +807,11 @@ class OssClient * Creates a play list file for the LiveChannel * * @param string $bucket bucket name - * @param string channelName $channelName + * @param string channelName $channelName * @param string $playlistName The playlist name, must end with ".m3u8". - * @param array $setTime startTime and EndTime in unix time. No more than 1 day. + * @param array $setTime startTime and EndTime in unix time. No more than 1 day. + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function postVodPlaylist($bucket, $channelName, $playlistName, $setTime) { @@ -899,7 +822,7 @@ class OssClient $options[self::OSS_SUB_RESOURCE] = 'vod'; $options[self::OSS_LIVE_CHANNEL_END_TIME] = $setTime['EndTime']; $options[self::OSS_LIVE_CHANNEL_START_TIME] = $setTime['StartTime']; - + $response = $this->auth($options); $result = new PutSetDeleteResult($response); return $result->getData(); @@ -911,8 +834,8 @@ class OssClient * @param string $bucket bucket name * @param string channelName $channelName * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function deleteBucketLiveChannel($bucket, $channelName, $options = NULL) { @@ -934,8 +857,8 @@ class OssClient * @param string channelName $channelName * @param int timeout timeout value in seconds * @param array $options - * @return string The signed pushing streaming url * @throws OssException + * @return The signed pushing streaming url */ public function signRtmpUrl($bucket, $channelName, $timeout = 60, $options = NULL) { @@ -954,12 +877,9 @@ class OssClient $resource = '/' . $bucket . '/' . $channelName; $string_to_sign = $expires . "\n" . $cano_params . $resource; - $cred = $this->provider->getCredentials(); - $this->checkCredentials($cred); + $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true)); - $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $cred->getAccessKeySecret(), true)); - - $query_items[] = 'OSSAccessKeyId=' . rawurlencode($cred->getAccessKeyId()); + $query_items[] = 'OSSAccessKeyId=' . rawurlencode($this->accessKeyId); $query_items[] = 'Expires=' . rawurlencode($expires); $query_items[] = 'Signature=' . rawurlencode($signature); @@ -973,8 +893,8 @@ class OssClient * @param string $channelName channel name * @param int $expiration expiration time of the Url, unix epoch, since 1970.1.1 00.00.00 UTC * @param array $options - * @return string The signed pushing streaming url * @throws OssException + * @return The signed pushing streaming url */ public function generatePresignedRtmpUrl($bucket, $channelName, $expiration, $options = NULL) { @@ -992,12 +912,9 @@ class OssClient $resource = '/' . $bucket . '/' . $channelName; $string_to_sign = $expiration . "\n" . $cano_params . $resource; - $cred = $this->provider->getCredentials(); - $this->checkCredentials($cred); + $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true)); - $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $cred->getAccessKeySecret(), true)); - - $query_items[] = 'OSSAccessKeyId=' . rawurlencode($cred->getAccessKeyId()); + $query_items[] = 'OSSAccessKeyId=' . rawurlencode($this->accessKeyId); $query_items[] = 'Expires=' . rawurlencode($expiration); $query_items[] = 'Signature=' . rawurlencode($signature); @@ -1006,8 +923,8 @@ class OssClient /** * Precheck the CORS request. Before sending a CORS request, a preflight request (OPTIONS) is sent with the specific origin. - * HTTP METHOD and headers information are sent to OSS as well for evaluating if the CORS request is allowed. - * + * HTTP METHOD and headers information are sent to OSS as well for evaluating if the CORS request is allowed. + * * Note: OSS could enable the CORS on the bucket by calling putBucketCors. Once CORS is enabled, the OSS could evaluate accordingto the preflight request. * * @param string $bucket bucket name @@ -1016,8 +933,9 @@ class OssClient * @param string $request_method The actual HTTP method which will be used in CORS request * @param string $request_headers The actual HTTP headers which will be used in CORS request * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return array + * @throws OssException + * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/OptionObject.html */ public function optionsObject($bucket, $object, $origin, $request_method, $request_headers, $options = NULL) { @@ -1025,9 +943,11 @@ class OssClient $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_OPTIONS; $options[self::OSS_OBJECT] = $object; - $options[self::OSS_HEADERS][self::OSS_OPTIONS_ORIGIN] = $origin; - $options[self::OSS_HEADERS][self::OSS_OPTIONS_REQUEST_HEADERS] = $request_headers; - $options[self::OSS_HEADERS][self::OSS_OPTIONS_REQUEST_METHOD] = $request_method; + $options[self::OSS_HEADERS] = array( + self::OSS_OPTIONS_ORIGIN => $origin, + self::OSS_OPTIONS_REQUEST_HEADERS => $request_headers, + self::OSS_OPTIONS_REQUEST_METHOD => $request_method + ); $response = $this->auth($options); $result = new HeaderResult($response); return $result->getData(); @@ -1039,14 +959,15 @@ class OssClient * @param string $bucket bucket name * @param LifecycleConfig $lifecycleConfig LifecycleConfig instance * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function putBucketLifecycle($bucket, $lifecycleConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'lifecycle'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $lifecycleConfig->serializeToXml(); @@ -1060,14 +981,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return LifecycleConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return LifecycleConfig */ public function getBucketLifecycle($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'lifecycle'; $response = $this->auth($options); $result = new GetLifecycleResult($response); @@ -1079,14 +1001,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function deleteBucketLifecycle($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'lifecycle'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -1095,19 +1018,20 @@ class OssClient /** * Sets a bucket's referer, which has a whitelist of referrer and specifies if empty referer is allowed. - * Checks out API document for more details about "Bucket Referer" + * Checks out API document for more details about "Bucket Referer" * * @param string $bucket bucket name * @param RefererConfig $refererConfig * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function putBucketReferer($bucket, $refererConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'referer'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $refererConfig->serializeToXml(); @@ -1118,18 +1042,19 @@ class OssClient /** * Gets the bucket's Referer - * Checks out API document for more details about "Bucket Referer" + * Checks out API document for more details about "Bucket Referer" * * @param string $bucket bucket name * @param array $options - * @return RefererConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return RefererConfig */ public function getBucketReferer($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'referer'; $response = $this->auth($options); $result = new GetRefererResult($response); @@ -1143,14 +1068,15 @@ class OssClient * @param string $bucket bucket name * @param int $storageCapacity * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function putBucketStorageCapacity($bucket, $storageCapacity, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'qos'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $storageCapacityConfig = new StorageCapacityConfig($storageCapacity); @@ -1165,14 +1091,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return int|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return int */ public function getBucketStorageCapacity($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'qos'; $response = $this->auth($options); $result = new GetStorageCapacityResult($response); @@ -1184,33 +1111,35 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return BucketInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return BucketInfo */ public function getBucketInfo($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'bucketInfo'; $response = $this->auth($options); $result = new GetBucketInfoResult($response); return $result->getData(); } - /** + /** * Get the stat of the bucket * * @param string $bucket bucket name * @param array $options - * @return BucketStat|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return BucketStat */ public function getBucketStat($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'stat'; $response = $this->auth($options); $result = new GetBucketStatResult($response); @@ -1223,14 +1152,15 @@ class OssClient * @param string $bucket bucket name * @param string $policy policy json format content * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function putBucketPolicy($bucket, $policy, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'policy'; $options[self::OSS_CONTENT_TYPE] = 'application/json'; $options[self::OSS_CONTENT] = $policy; @@ -1244,14 +1174,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return string|null policy json content - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string policy json content */ public function getBucketPolicy($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'policy'; $response = $this->auth($options); $result = new BodyResult($response); @@ -1263,14 +1194,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function deleteBucketPolicy($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'policy'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -1283,14 +1215,15 @@ class OssClient * @param string $bucket bucket name * @param ServerSideEncryptionConfig $sseConfig * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function putBucketEncryption($bucket, $sseConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'encryption'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $sseConfig->serializeToXml(); @@ -1304,14 +1237,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return ServerSideEncryptionConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return ServerSideEncryptionConfig */ public function getBucketEncryption($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'encryption'; $response = $this->auth($options); $result = new GetBucketEncryptionResult($response); @@ -1323,14 +1257,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function deleteBucketEncryption($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'encryption'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -1343,14 +1278,15 @@ class OssClient * @param string $bucket bucket name * @param string $payer * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function putBucketRequestPayment($bucket, $payer, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'requestPayment'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $config = new RequestPaymentConfig($payer); @@ -1365,14 +1301,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getBucketRequestPayment($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'requestPayment'; $response = $this->auth($options); $result = new GetBucketRequestPaymentResult($response); @@ -1385,14 +1322,15 @@ class OssClient * @param string $bucket bucket name * @param TaggingConfig $taggingConfig * @param array $options + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function putBucketTags($bucket, $taggingConfig, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $options[self::OSS_CONTENT] = $taggingConfig->serializeToXml(); @@ -1406,14 +1344,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return TaggingConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return TaggingConfig */ public function getBucketTags($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING; $response = $this->auth($options); $result = new GetBucketTagsResult($response); @@ -1427,20 +1366,21 @@ class OssClient * @param string $bucket bucket name * @param tag[] $tags (optional) * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function deleteBucketTags($bucket, $tags = NULL, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; if (empty($tags)) { $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING; } else { $value = ''; - foreach ($tags as $tag) { - $value .= $tag->getKey() . ','; + foreach ($tags as $tag ) { + $value .= $tag->getKey().','; } $value = rtrim($value, ','); $options[self::OSS_TAGGING] = $value; @@ -1456,14 +1396,15 @@ class OssClient * @param string $bucket bucket name * @param string $status * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function putBucketVersioning($bucket, $status, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'versioning'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $config = new VersioningConfig($status); @@ -1478,14 +1419,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getBucketVersioning($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'versioning'; $response = $this->auth($options); $result = new GetBucketVersioningResult($response); @@ -1498,14 +1440,15 @@ class OssClient * @param string $bucket bucket name * @param int $day * @param array $options - * @return string|null returns upload id - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string returns uploadid */ public function initiateBucketWorm($bucket, $day, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_METHOD] = self::OSS_HTTP_POST; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'worm'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $config = new InitiateWormConfig($day); @@ -1520,34 +1463,36 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function abortBucketWorm($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'worm'; $response = $this->auth($options); $result = new PutSetDeleteResult($response); return $result->getData(); } - /** + /** * Complete a bucket's worm * * @param string $bucket bucket name * @param string $wormId * @param array $options - * @return string|null returns upload id - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string returns uploadid */ public function completeBucketWorm($bucket, $wormId, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_METHOD] = self::OSS_HTTP_POST; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_WORM_ID] = $wormId; $options[self::OSS_CONTENT] = ''; $response = $this->auth($options); @@ -1562,14 +1507,15 @@ class OssClient * @param string $wormId * @param int $day * @param array $options - * @return string|null returns upload id - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string returns uploadid */ public function extendBucketWorm($bucket, $wormId, $day, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_METHOD] = self::OSS_HTTP_POST; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_WORM_ID] = $wormId; $options[self::OSS_SUB_RESOURCE] = 'wormExtend'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; @@ -1585,14 +1531,15 @@ class OssClient * * @param string $bucket bucket name * @param array $options - * @return string|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string */ public function getBucketWorm($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'worm'; $response = $this->auth($options); $result = new GetBucketWormResult($response); @@ -1604,16 +1551,17 @@ class OssClient * Put Bucket TransferAcceleration * @param $bucket * @param $enabled boolean - * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @param null $options + * @return null + * @throws OssException */ - public function putBucketTransferAcceleration($bucket, $enabled, $options = NULL) + public function putBucketTransferAcceleration($bucket,$enabled,$options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_PUT; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'transferAcceleration'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $config = new TransferAccelerationConfig(); @@ -1627,15 +1575,16 @@ class OssClient /** * Put Bucket TransferAcceleration * @param $bucket - * @param array $options - * @return boolean|null - * @throws OssException|RequestCore_Exception + * @param null $options + * @return enabled boolean + * @throws OssException */ - public function getBucketTransferAcceleration($bucket, $options = NULL) + public function getBucketTransferAcceleration($bucket,$options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'transferAcceleration'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $response = $this->auth($options); @@ -1655,30 +1604,31 @@ class OssClient * 'marker' => The key of returned object must be greater than the 'marker'. *) * Prefix and marker are for filtering and paging. Their length must be less than 256 bytes - * @return ObjectListInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return ObjectListInfo */ public function listObjects($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array(); $options[self::OSS_QUERY_STRING] = array_merge( $query, array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL, - self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/', - self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '', - self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE, - self::OSS_MARKER => isset($options[self::OSS_MARKER]) ? $options[self::OSS_MARKER] : '') + self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/', + self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '', + self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE, + self::OSS_MARKER => isset($options[self::OSS_MARKER]) ? $options[self::OSS_MARKER] : '') ); $response = $this->auth($options); $result = new ListObjectsResult($response); return $result->getData(); } - - + + /** * Lists the bucket's object list v2 (in ObjectListInfoV2) * @@ -1692,33 +1642,37 @@ class OssClient * 'continuation-token' => The token from which the list operation must start. *) * Prefix, start-after and continuation-token are for filtering and paging. Their length must be less than 256 bytes - * @return ObjectListInfoV2|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return ObjectListInfoV2 */ public function listObjectsV2($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array(); $temp = array( - self::OSS_LIST_TYPE => 2, + self::OSS_LIST_TYPE=>2, self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL, self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/', self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '', self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE, self::OSS_START_AFTER => isset($options[self::OSS_START_AFTER]) ? $options[self::OSS_START_AFTER] : '', ); - if (isset($options[self::OSS_CONTINUATION_TOKEN])) { + if(isset($options[self::OSS_CONTINUATION_TOKEN])){ $temp[self::OSS_CONTINUATION_TOKEN] = $options[self::OSS_CONTINUATION_TOKEN]; } $options[self::OSS_QUERY_STRING] = array_merge( - $query, $temp + $query,$temp ); $response = $this->auth($options); $result = new ListObjectsV2Result($response); return $result->getData(); } + + + /** * Lists the bucket's object with version information (in ObjectListInfo) @@ -1733,24 +1687,25 @@ class OssClient * 'version-id-marker' => The version id of returned object must be greater than the 'version-id-marker'. *) * Prefix and marker are for filtering and paging. Their length must be less than 256 bytes - * @return ObjectVersionListInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return ObjectListInfo */ public function listObjectVersions($bucket, $options = NULL) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_METHOD] = self::OSS_HTTP_GET; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'versions'; $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array(); $options[self::OSS_QUERY_STRING] = array_merge( $query, array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL, - self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/', - self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '', - self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE, - self::OSS_KEY_MARKER => isset($options[self::OSS_KEY_MARKER]) ? $options[self::OSS_KEY_MARKER] : '', - self::OSS_VERSION_ID_MARKER => isset($options[self::OSS_VERSION_ID_MARKER]) ? $options[self::OSS_VERSION_ID_MARKER] : '') + self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/', + self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '', + self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE, + self::OSS_KEY_MARKER => isset($options[self::OSS_KEY_MARKER]) ? $options[self::OSS_KEY_MARKER] : '', + self::OSS_VERSION_ID_MARKER => isset($options[self::OSS_VERSION_ID_MARKER]) ? $options[self::OSS_VERSION_ID_MARKER] : '') ); $response = $this->auth($options); @@ -1766,8 +1721,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null */ public function createObjectDir($bucket, $object, $options = NULL) { @@ -1788,8 +1742,7 @@ class OssClient * @param string $object objcet name * @param string $content The content object * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null */ public function putObject($bucket, $object, $content, $options = NULL) { @@ -1811,18 +1764,18 @@ class OssClient $content_md5 = base64_encode(md5($content, true)); $options[self::OSS_CONTENT_MD5] = $content_md5; } - + if (!isset($options[self::OSS_CONTENT_TYPE])) { $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object); } $response = $this->auth($options); - + if (isset($options[self::OSS_CALLBACK]) && !empty($options[self::OSS_CALLBACK])) { $result = new CallbackResult($response); } else { $result = new PutSetDeleteResult($response); } - + return $result->getData(); } @@ -1833,10 +1786,9 @@ class OssClient * @param string $symlink symlink name * @param string $targetObject targetObject name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null */ - public function putSymlink($bucket, $symlink, $targetObject, $options = NULL) + public function putSymlink($bucket, $symlink ,$targetObject, $options = NULL) { $this->precheckCommon($bucket, $symlink, $options); @@ -1852,12 +1804,11 @@ class OssClient } /** - * Gets symlink + * gets symlink * @param string $bucket bucket name * @param string $symlink symlink name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null */ public function getSymlink($bucket, $symlink, $options = NULL) { @@ -1880,19 +1831,19 @@ class OssClient * @param string $object object name * @param string $file local file path * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null + * @throws OssException */ public function uploadFile($bucket, $object, $file, $options = NULL) { $this->precheckCommon($bucket, $object, $options); OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid"); - $file = $this->encodeFilePath($file); + $file = OssUtil::encodePath($file); if (!file_exists($file)) { throw new OssException($file . " file does not exist"); } $options[self::OSS_FILE_UPLOAD] = $file; - $file_size = sprintf('%u', filesize($options[self::OSS_FILE_UPLOAD])); + $file_size = sprintf('%u',filesize($options[self::OSS_FILE_UPLOAD])); $is_check_md5 = $this->isCheckMD5($options); if ($is_check_md5) { $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true)); @@ -1917,8 +1868,8 @@ class OssClient * @param string $object object name * @param resource $handle file handle * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null + * @throws OssException */ public function uploadStream($bucket, $object, $handle, $options = NULL) { @@ -1942,8 +1893,7 @@ class OssClient $options[self::OSS_BUCKET] = $bucket; $options[self::OSS_OBJECT] = $object; if (!isset($options[self::OSS_CONTENT_LENGTH])) { - $stat = fstat($handle); - $options[self::OSS_CONTENT_LENGTH] = $stat[self::OSS_SIZE]; + $options[self::OSS_CONTENT_LENGTH] = fstat($handle)[self::OSS_SIZE]; } $response = $this->auth($options); $result = new PutSetDeleteResult($response); @@ -1957,8 +1907,8 @@ class OssClient * @param string $object objcet name * @param string $content content to append * @param array $options - * @return int|null next append position - * @throws OssException|RequestCore_Exception + * @return int next append position + * @throws OssException */ public function appendObject($bucket, $object, $content, $position, $options = NULL) { @@ -1970,12 +1920,13 @@ class OssClient $options[self::OSS_OBJECT] = $object; $options[self::OSS_SUB_RESOURCE] = 'append'; $options[self::OSS_POSITION] = strval($position); + if (!isset($options[self::OSS_LENGTH])) { $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]); } else { $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH]; } - + $is_check_md5 = $this->isCheckMD5($options); if ($is_check_md5) { $content_md5 = base64_encode(md5($content, true)); @@ -1997,20 +1948,20 @@ class OssClient * @param string $object object name * @param string $file The local file path to append with * @param array $options - * @return int|null next append position - * @throws OssException|RequestCore_Exception + * @return int next append position + * @throws OssException */ public function appendFile($bucket, $object, $file, $position, $options = NULL) { $this->precheckCommon($bucket, $object, $options); OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid"); - $file = $this->encodeFilePath($file); + $file = OssUtil::encodePath($file); if (!file_exists($file)) { throw new OssException($file . " file does not exist"); } $options[self::OSS_FILE_UPLOAD] = $file; - $file_size = sprintf('%u', filesize($options[self::OSS_FILE_UPLOAD])); + $file_size = sprintf('%u',filesize($options[self::OSS_FILE_UPLOAD])); $is_check_md5 = $this->isCheckMD5($options); if ($is_check_md5) { $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true)); @@ -2041,7 +1992,7 @@ class OssClient * @param string $toObject Target object name * @param array $options * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException */ public function copyObject($fromBucket, $fromObject, $toBucket, $toObject, $options = NULL) { @@ -2052,10 +2003,14 @@ class OssClient $options[self::OSS_OBJECT] = $toObject; $param = '/' . $fromBucket . '/' . rawurlencode($fromObject); if (isset($options[self::OSS_VERSION_ID])) { - $param = $param . '?versionId=' . $options[self::OSS_VERSION_ID]; + $param = $param . '?versionId='.$options[self::OSS_VERSION_ID]; unset($options[self::OSS_VERSION_ID]); } - $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = $param; + if (isset($options[self::OSS_HEADERS])) { + $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = $param; + } else { + $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_COPY_SOURCE => $param); + } $response = $this->auth($options); $result = new CopyObjectResult($response); return $result->getData(); @@ -2067,8 +2022,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param string $options Checks out the SDK document for the detail - * @return array|null - * @throws OssException|RequestCore_Exception + * @return array */ public function getObjectMeta($bucket, $object, $options = NULL) { @@ -2081,15 +2035,14 @@ class OssClient return $result->getData(); } - /** - * Gets the simplified metadata of a object. + /** + * Gets the simplified metadata of a object. * Simplified metadata includes ETag, Size, LastModified. * * @param string $bucket bucket name * @param string $object object name * @param string $options Checks out the SDK document for the detail - * @return array|null - * @throws OssException|RequestCore_Exception + * @return array */ public function getSimplifiedObjectMeta($bucket, $object, $options = NULL) { @@ -2109,8 +2062,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null */ public function deleteObject($bucket, $object, $options = NULL) { @@ -2129,8 +2081,8 @@ class OssClient * @param string $bucket bucket name * @param array $objects object list * @param array $options - * @return array|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function deleteObjects($bucket, $objects, $options = null) { @@ -2140,6 +2092,7 @@ class OssClient } $options[self::OSS_METHOD] = self::OSS_HTTP_POST; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'delete'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $quiet = 'false'; @@ -2163,8 +2116,8 @@ class OssClient * @param string $bucket bucket name * @param array $objects DeleteObjectInfo list * @param array $options - * @return DeletedObjectInfo|null - * @throws OssException|RequestCore_Exception + * @return ResponseCore + * @throws null */ public function deleteObjectVersions($bucket, $objects, $options = null) { @@ -2174,6 +2127,7 @@ class OssClient } $options[self::OSS_METHOD] = self::OSS_HTTP_POST; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'delete'; $options[self::OSS_CONTENT_TYPE] = 'application/xml'; $quiet = 'false'; @@ -2197,8 +2151,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param array $options It must contain ALIOSS::OSS_FILE_DOWNLOAD. And ALIOSS::OSS_RANGE is optional and empty means to download the whole file. - * @return string|null - * @throws OssException|RequestCore_Exception + * @return string */ public function getObject($bucket, $object, $options = NULL) { @@ -2231,8 +2184,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param array $options - * @return bool|null True:object exists; False:object does not exist - * @throws OssException|RequestCore_Exception| + * @return bool True:object exists; False:object does not exist */ public function doesObjectExist($bucket, $object, $options = NULL) { @@ -2251,8 +2203,8 @@ class OssClient * * @param string $bucket bucket name * @param string $object object name - * @return array|null - * @throws OssException|RequestCore_Exception + * @return null + * @throws OssException */ public function restoreObject($bucket, $object, $options = NULL) { @@ -2277,8 +2229,8 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param TaggingConfig $taggingConfig - * @return array|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return null */ public function putObjectTagging($bucket, $object, $taggingConfig, $options = NULL) { @@ -2299,8 +2251,8 @@ class OssClient * * @param string $bucket * @param string $object - * @return TaggingConfig|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return TaggingConfig */ public function getObjectTagging($bucket, $object, $options = NULL) { @@ -2319,8 +2271,8 @@ class OssClient * * @param string $bucket * @param string $object - * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return TaggingConfig */ public function deleteObjectTagging($bucket, $object, $options = NULL) { @@ -2340,8 +2292,7 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param string $process process script - * @return string|null process result, json format - * @throws OssException|RequestCore_Exception| + * @return string process result, json format */ public function processObject($bucket, $object, $process, $options = NULL) { @@ -2351,33 +2302,7 @@ class OssClient $options[self::OSS_OBJECT] = $object; $options[self::OSS_SUB_RESOURCE] = 'x-oss-process'; $options[self::OSS_CONTENT_TYPE] = 'application/octet-stream'; - $options[self::OSS_CONTENT] = 'x-oss-process=' . $process; - $response = $this->auth($options); - $result = new BodyResult($response); - return $result->getData(); - } - - - /** - * Async Process the object - * - * @param string $bucket bucket name - * @param string $object object name - * @param string $asyncProcess async process script - * @param null $options - * @return string|null process result, json format - * @throws OssException - * @throws RequestCore_Exception - */ - public function asyncProcessObject($bucket, $object, $asyncProcess, $options = NULL) - { - $this->precheckCommon($bucket, $object, $options); - $options[self::OSS_BUCKET] = $bucket; - $options[self::OSS_METHOD] = self::OSS_HTTP_POST; - $options[self::OSS_OBJECT] = $object; - $options[self::OSS_SUB_RESOURCE] = 'x-oss-async-process'; - $options[self::OSS_CONTENT_TYPE] = 'application/octet-stream'; - $options[self::OSS_CONTENT] = 'x-oss-async-process=' . $asyncProcess; + $options[self::OSS_CONTENT] = 'x-oss-process='.$process; $response = $this->auth($options); $result = new BodyResult($response); return $result->getData(); @@ -2406,7 +2331,7 @@ class OssClient * It must be only called by upload_Part(). * * @param integer $file_size File size - * @param integer $partSize part size. Default is 5MB + * @param integer $partSize part大小,part size. Default is 5MB * @return array An array contains key-value pairs--the key is `seekTo`and value is `length`. */ public function generateMultiuploadParts($file_size, $partSize = 5242880) @@ -2432,8 +2357,8 @@ class OssClient * @param string $bucket bucket name * @param string $object object name * @param array $options Key-Value array - * @return string|null returns upload id - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return string returns uploadid */ public function initiateMultipartUpload($bucket, $object, $options = NULL) { @@ -2462,8 +2387,8 @@ class OssClient * @param string $object object name * @param string $uploadId * @param array $options Key-Value array - * @return string|null eTag - * @throws OssException|RequestCore_Exception + * @return string eTag + * @throws OssException */ public function uploadPart($bucket, $object, $uploadId, $options = null) { @@ -2491,8 +2416,8 @@ class OssClient * @param string $object object name * @param string $uploadId uploadId * @param array $options Key-Value array - * @return ListPartsInfo|null - * @throws OssException|RequestCore_Exception + * @return ListPartsInfo + * @throws OssException */ public function listParts($bucket, $object, $uploadId, $options = null) { @@ -2521,7 +2446,7 @@ class OssClient * @param string $uploadId uploadId * @param array $options Key-Value name * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException */ public function abortMultipartUpload($bucket, $object, $uploadId, $options = NULL) { @@ -2543,8 +2468,8 @@ class OssClient * @param string $uploadId uploadId * @param array $listParts array( array("PartNumber"=> int, "ETag"=>string)) * @param array $options Key-Value array + * @throws OssException * @return null - * @throws OssException|RequestCore_Exception */ public function completeMultipartUpload($bucket, $object, $uploadId, $listParts, $options = NULL) { @@ -2556,7 +2481,7 @@ class OssClient $options[self::OSS_CONTENT_TYPE] = 'application/xml'; if (is_array($listParts)) { $options[self::OSS_CONTENT] = OssUtil::createCompleteMultipartUploadXmlBody($listParts); - } else { + } else { $options[self::OSS_CONTENT] = ""; } @@ -2574,14 +2499,15 @@ class OssClient * * @param string $bucket bucket * @param array $options key-value array--expected keys are 'delimiter', 'key-marker', 'max-uploads', 'prefix', 'upload-id-marker' - * @return ListMultipartUploadInfo|null - * @throws OssException|RequestCore_Exception + * @throws OssException + * @return ListMultipartUploadInfo */ public function listMultipartUploads($bucket, $options = null) { $this->precheckCommon($bucket, NULL, $options, false); $options[self::OSS_METHOD] = self::OSS_HTTP_GET; $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = '/'; $options[self::OSS_SUB_RESOURCE] = 'uploads'; foreach (array('delimiter', 'key-marker', 'max-uploads', 'prefix', 'upload-id-marker') as $param) { @@ -2612,7 +2538,7 @@ class OssClient * @param string $uploadId Upload Id * @param array $options Key-Value array---it should have 'start' or 'end' key to specify the range of the source object to copy. If it's not specifed, the whole object is copied. * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException */ public function uploadPartCopy($fromBucket, $fromObject, $toBucket, $toObject, $partNumber, $uploadId, $options = NULL) { @@ -2640,7 +2566,7 @@ class OssClient $param = '/' . $fromBucket . '/' . rawurlencode($fromObject); if (isset($options[self::OSS_VERSION_ID])) { - $param = $param . '?versionId=' . $options[self::OSS_VERSION_ID]; + $param = $param . '?versionId='.$options[self::OSS_VERSION_ID]; unset($options[self::OSS_VERSION_ID]); } @@ -2659,7 +2585,7 @@ class OssClient * @param string $file The local file to upload * @param array $options Key-Value array * @return null - * @throws OssException|RequestCore_Exception + * @throws OssException */ public function multiuploadFile($bucket, $object, $file, $options = null) { @@ -2671,7 +2597,7 @@ class OssClient if (empty($file)) { throw new OssException("parameter invalid, file is empty"); } - $uploadFile = $this->encodeFilePath($file); + $uploadFile = OssUtil::encodePath($file); if (!isset($options[self::OSS_CONTENT_TYPE])) { $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $uploadFile); } @@ -2681,10 +2607,10 @@ class OssClient if (isset($options[self::OSS_CONTENT_LENGTH])) { $upload_file_size = (integer)$options[self::OSS_CONTENT_LENGTH]; } else { - $upload_file_size = sprintf('%u', filesize($uploadFile)); + $upload_file_size = sprintf('%u',filesize($uploadFile)); if ($upload_file_size !== false) { - $upload_file_size -= $upload_position; + $upload_file_size -= $upload_position; } } @@ -2746,7 +2672,7 @@ class OssClient $cmp_options = array( OssClient::OSS_HEADERS => array( OssClient::OSS_REQUEST_PAYER => $options[self::OSS_HEADERS][self::OSS_REQUEST_PAYER], - )); + )); } return $this->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts, $cmp_options); } @@ -2770,7 +2696,7 @@ class OssClient if (!is_string($prefix)) throw new OssException("parameter error, prefix is not string"); if (empty($localDirectory)) throw new OssException("parameter error, localDirectory is empty"); $directory = $localDirectory; - $directory = $this->encodeFilePath($directory); + $directory = OssUtil::encodePath($directory); //If it's not the local directory, throw OSSException. if (!is_dir($directory)) { throw new OssException('parameter error: ' . $directory . ' is not a directory, please check it'); @@ -2788,9 +2714,7 @@ class OssClient self::OSS_PART_SIZE => self::OSS_MIN_PART_SIZE, self::OSS_CHECK_MD5 => $checkMd5, ); - //mbstring to utf-8 - $fileName = $this->decodeFilePath($item['file']); - $realObject = (!empty($prefix) ? $prefix . '/' : '') . $fileName; + $realObject = (!empty($prefix) ? $prefix . '/' : '') . $item['file']; try { $this->multiuploadFile($bucket, $realObject, $item['path'], $options); @@ -2816,8 +2740,22 @@ class OssClient */ public function signUrl($bucket, $object, $timeout = 60, $method = self::OSS_HTTP_GET, $options = NULL) { - $expiration = time() + $timeout; - return $this->generatePresignedUrl($bucket, $object, $expiration, $method, $options); + $this->precheckCommon($bucket, $object, $options); + //method + if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) { + throw new OssException("method is invalid"); + } + $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = $object; + $options[self::OSS_METHOD] = $method; + if (!isset($options[self::OSS_CONTENT_TYPE])) { + $options[self::OSS_CONTENT_TYPE] = ''; + } + $timeout = time() + $timeout; + $options[self::OSS_PREAUTH] = $timeout; + $options[self::OSS_DATE] = $timeout; + $this->setSignStsInUrl(true); + return $this->auth($options); } /** @@ -2834,47 +2772,21 @@ class OssClient */ public function generatePresignedUrl($bucket, $object, $expiration, $method = self::OSS_HTTP_GET, $options = NULL) { - $this->precheckObjectExt($object, $this->enableStrictObjName); $this->precheckCommon($bucket, $object, $options); - $cred = $this->provider->getCredentials(); //method if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) { throw new OssException("method is invalid"); } - // Should https or http be used? - $scheme = $this->useSSL ? 'https://' : 'http://'; - // gets the host name. If the host name is public domain or private domain, form a third level domain by prefixing the bucket name on the domain name. - $hostname = $this->generateHostname($bucket); - $path = $this->generatePath($bucket, $object); - $headers = $this->generateHeaders($options, ''); - $query_string = $this->generateQueryString($options); - $query_string = empty($query_string) ? '' : '?' . $query_string; - $requestUrl = $scheme . $hostname . $path . $query_string; - //Creates the request - $request = new RequestCore($requestUrl); - $request->set_method($method); - if (isset($options[self::OSS_CALLBACK])) { - $headers[self::OSS_CALLBACK] = base64_encode($options[self::OSS_CALLBACK]); + $options[self::OSS_BUCKET] = $bucket; + $options[self::OSS_OBJECT] = $object; + $options[self::OSS_METHOD] = $method; + if (!isset($options[self::OSS_CONTENT_TYPE])) { + $options[self::OSS_CONTENT_TYPE] = ''; } - if (isset($options[self::OSS_CALLBACK_VAR])) { - $headers[self::OSS_CALLBACK_VAR] = base64_encode($options[self::OSS_CALLBACK_VAR]); - } - foreach ($headers as $header_key => $header_value) { - $header_value = trim($header_value); - if (empty($header_value)) { - continue; - } - $request->add_header($header_key, $header_value); - } - $signingOpt = array( - 'bucket' => $bucket, - 'key' => $object, - 'region' => $this->getRegion(), - 'product' => $this->getProduct(), - 'expiration' => $expiration, - ); - $this->signer->presign($request, $cred, $signingOpt); - return $request->request_url; + $options[self::OSS_PREAUTH] = $expiration; + $options[self::OSS_DATE] = $expiration; + $this->setSignStsInUrl(true); + return $this->auth($options); } /** @@ -2901,9 +2813,6 @@ class OssClient private function precheckBucket($bucket, $errMsg = 'bucket is not allowed empty') { OssUtil::throwOssExceptionWithMessageIfEmpty($bucket, $errMsg); - if (!OssUtil::validateBucket($bucket)) { - throw new OssException('"' . $bucket . '"' . 'bucket name is invalid'); - } } /** @@ -2915,31 +2824,12 @@ class OssClient private function precheckObject($object) { OssUtil::throwOssExceptionWithMessageIfEmpty($object, "object name is empty"); - if (!OssUtil::validateObject($object)) { - throw new OssException('"' . $object . '"' . ' object name is invalid'); - } } /** - * validates object name start with ? or not - * @param $object string - * @param $strict boolean - * @throws OssException - */ - private function precheckObjectExt($object, $strict) - { - $this->precheckObject($object); - if ($strict) { - if (is_string($object) && $object[0] === "?") { - throw new OssException('"' . $object . '"' . ' object name cannot start with `?`'); - } - } - } - - /** - * Check option restore + * 校验option restore * - * @param $storage string + * @param string $restore * @throws OssException */ private function precheckStorage($storage) @@ -3005,7 +2895,7 @@ class OssClient } /** - * Gets value of the specified key from the options + * Gets value of the specified key from the options * * @param array $options * @param string $key @@ -3062,32 +2952,46 @@ class OssClient * Validates and executes the request according to OSS API protocol. * * @param array $options - * @return ResponseCore|string + * @return ResponseCore * @throws OssException * @throws RequestCore_Exception */ private function auth($options) { OssUtil::validateOptions($options); - //Object Encoding + //Validates bucket, not required for list_bucket + $this->authPrecheckBucket($options); + //Validates object + $this->authPrecheckObject($options); + //object name encoding must be UTF-8 $this->authPrecheckObjectEncoding($options); //Validates ACL $this->authPrecheckAcl($options); - $cred = $this->provider->getCredentials(); - $this->checkCredentials($cred); - - $bucket = isset($options[self::OSS_BUCKET]) ? $options[self::OSS_BUCKET] : ''; - $object = isset($options[self::OSS_OBJECT]) ? $options[self::OSS_OBJECT] : ''; - // Should https or http be used? $scheme = $this->useSSL ? 'https://' : 'http://'; // gets the host name. If the host name is public domain or private domain, form a third level domain by prefixing the bucket name on the domain name. - $hostname = $this->generateHostname($bucket); - $path = $this->generatePath($bucket, $object); + $hostname = $this->generateHostname($options[self::OSS_BUCKET]); + $string_to_sign = ''; $headers = $this->generateHeaders($options, $hostname); + $signable_query_string_params = $this->generateSignableQueryStringParam($options); + $signable_query_string = OssUtil::toQueryString($signable_query_string_params); + $resource_uri = $this->generateResourceUri($options); + //Generates the URL (add query parameters) + $conjunction = '?'; + $non_signable_resource = ''; + if (isset($options[self::OSS_SUB_RESOURCE])) { + $conjunction = '&'; + } + if ($signable_query_string !== '') { + $signable_query_string = $conjunction . $signable_query_string; + $conjunction = '&'; + } $query_string = $this->generateQueryString($options); - $query_string = empty($query_string) ? '' : '?' . $query_string; - $requestUrl = $scheme . $hostname . $path . $query_string; + if ($query_string !== '') { + $non_signable_resource .= $conjunction . $query_string; + $conjunction = '&'; + } + $requestUrl = $scheme . $hostname . $resource_uri . $signable_query_string . $non_signable_resource; //Creates the request $request = new RequestCore($requestUrl, $this->requestProxy); @@ -3127,12 +3031,15 @@ class OssClient $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]); } } + if (isset($options[self::OSS_METHOD])) { $request->set_method($options[self::OSS_METHOD]); + $string_to_sign .= $options[self::OSS_METHOD] . "\n"; } + if (isset($options[self::OSS_CONTENT])) { $request->set_body($options[self::OSS_CONTENT]); - if (isset($headers[self::OSS_CONTENT_TYPE]) && $headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') { + if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') { $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream'; } @@ -3151,31 +3058,44 @@ class OssClient $headers[self::OSS_ACCEPT_ENCODING] = ''; } - if (!isset($headers[self::OSS_CONTENT_TYPE])) { - $headers[self::OSS_CONTENT_TYPE] = self::DEFAULT_CONTENT_TYPE; - } + uksort($headers, 'strnatcasecmp'); foreach ($headers as $header_key => $header_value) { - $header_value = trim($header_value); - if (empty($header_value)) { - continue; + $header_value = str_replace(array("\r", "\n"), '', $header_value); + if ($header_value !== '' || $header_key === self::OSS_ACCEPT_ENCODING) { + $request->add_header($header_key, $header_value); } - $request->add_header($header_key, $header_value); - } - // sign request - $signingOpt = array( - 'bucket' => $bucket, - 'key' => $object, - 'region' => $this->getRegion(), - 'product' => $this->getProduct(), - ); - if (isset($options[self::OSS_ADDITIONAL_HEADERS])) { - $signingOpt['additionalHeaders'] = $options[self::OSS_ADDITIONAL_HEADERS]; + if ( + strtolower($header_key) === 'content-md5' || + strtolower($header_key) === 'content-type' || + strtolower($header_key) === 'date' || + (isset($options['self::OSS_PREAUTH']) && (integer)$options['self::OSS_PREAUTH'] > 0) + ) { + $string_to_sign .= $header_value . "\n"; + } elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX) { + $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n"; + } } + // Generates the signable_resource + $signable_resource = $this->generateSignableResource($options); + $signable_resource = rawurldecode($signable_resource) . urldecode($signable_query_string); + $string_to_sign_ordered = $string_to_sign; + $string_to_sign .= $signable_resource; - $this->signer->sign($request, $cred, $signingOpt); - $string_to_sign = isset($signingOpt['string_to_sign']) ? $signingOpt['string_to_sign'] : ''; + // Sort the strings to be signed. + $string_to_sign_ordered .= $this->stringToSignSorted($signable_resource); + + + $signature = base64_encode(hash_hmac('sha1', $string_to_sign_ordered, $this->accessKeySecret, true)); + $request->add_header('Authorization', 'OSS ' . $this->accessKeyId . ':' . $signature); + + if (isset($options[self::OSS_PREAUTH]) && (integer)$options[self::OSS_PREAUTH] > 0) { + $signed_url = $requestUrl . $conjunction . self::OSS_URL_ACCESS_KEY_ID . '=' . rawurlencode($this->accessKeyId) . '&' . self::OSS_URL_EXPIRES . '=' . $options[self::OSS_PREAUTH] . '&' . self::OSS_URL_SIGNATURE . '=' . rawurlencode($signature); + return $signed_url; + } elseif (isset($options[self::OSS_PREAUTH])) { + return $requestUrl; + } if ($this->timeout !== 0) { $request->timeout = $this->timeout; @@ -3206,7 +3126,7 @@ class OssClient $data = $this->auth($options); } } - + $this->redirects = 0; return $data; } @@ -3239,6 +3159,7 @@ class OssClient */ public function setSignStsInUrl($enable) { + $this->enableStsInUrl = $enable; } /** @@ -3257,6 +3178,37 @@ class OssClient $this->useSSL = $useSSL; } + /** + * Validates bucket name--throw OssException if it's invalid + * + * @param $options + * @throws OssException + */ + private function authPrecheckBucket($options) + { + if (!(('/' == $options[self::OSS_OBJECT]) && ('' == $options[self::OSS_BUCKET]) && ('GET' == $options[self::OSS_METHOD])) && !OssUtil::validateBucket($options[self::OSS_BUCKET])) { + throw new OssException('"' . $options[self::OSS_BUCKET] . '"' . 'bucket name is invalid'); + } + } + + /** + * + * Validates the object name--throw OssException if it's invalid. + * + * @param $options + * @throws OssException + */ + private function authPrecheckObject($options) + { + if (isset($options[self::OSS_OBJECT]) && $options[self::OSS_OBJECT] === '/') { + return; + } + + if (isset($options[self::OSS_OBJECT]) && !OssUtil::validateObject($options[self::OSS_OBJECT])) { + throw new OssException('"' . $options[self::OSS_OBJECT] . '"' . ' object name is invalid'); + } + } + /** * Checks the object's encoding. Convert it to UTF8 if it's in GBK or GB2312 * @@ -3264,29 +3216,20 @@ class OssClient */ private function authPrecheckObjectEncoding(&$options) { - if ($this->checkObjectEncoding !== true) { - return; - } - - if (!isset($options[self::OSS_OBJECT])) { - return; - } - + $tmp_object = $options[self::OSS_OBJECT]; try { - $tmp_object = $options[self::OSS_OBJECT]; - $encoding = array('UTF-8', 'GB2312', 'GBK'); - $encode = mb_detect_encoding($tmp_object, $encoding); - if ($encode === 'UTF-8' || $encode === false) { - return; + if (OssUtil::isGb2312($options[self::OSS_OBJECT])) { + $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8//IGNORE", $options[self::OSS_OBJECT]); + } elseif (OssUtil::checkChar($options[self::OSS_OBJECT], true)) { + $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8//IGNORE", $options[self::OSS_OBJECT]); } - $tmp_object = iconv($encode, "UTF-8", $tmp_object); - if ($tmp_object === false) { - return; - } - $options[self::OSS_OBJECT] = $tmp_object; } catch (\Exception $e) { - //IGNORE + try { + $tmp_object = iconv(mb_detect_encoding($tmp_object), "UTF-8", $tmp_object); + } catch (\Exception $e) { + } } + $options[self::OSS_OBJECT] = $tmp_object; } /** @@ -3313,7 +3256,7 @@ class OssClient */ private function generateHostname($bucket) { - if ($this->hostType === self::OSS_HOST_TYPE_IP || $this->hostType === self::OSS_HOST_TYPE_PATH_STYLE) { + if ($this->hostType === self::OSS_HOST_TYPE_IP) { $hostname = $this->hostname; } elseif ($this->hostType === self::OSS_HOST_TYPE_CNAME) { $hostname = $this->hostname; @@ -3325,42 +3268,45 @@ class OssClient } /** - * Gets the Uri path in the current request + * Gets the resource Uri in the current request * - * @param $bucket - * @param $object + * @param $options * @return string return the resource uri. */ - private function generatePath($bucket, $object) + private function generateResourceUri($options) { - $paths = array(); - // +bucket - if ('' !== $bucket) { - if ($this->hostType === self::OSS_HOST_TYPE_IP || $this->hostType === self::OSS_HOST_TYPE_PATH_STYLE) { - $paths[] = $bucket; - if ('' === $object) { - $paths[] = ''; - } + $resource_uri = ""; + + // resource_uri + bucket + if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) { + if ($this->hostType === self::OSS_HOST_TYPE_IP) { + $resource_uri = '/' . $options[self::OSS_BUCKET]; } } - // + object - if ('' !== $object && '/' !== $object) { - $paths[] = str_replace(array('%2F'), array('/'), rawurlencode($object)); + + // resource_uri + object + if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) { + $resource_uri .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT])); } - return '/' . implode('/', $paths); + + // resource_uri + sub_resource + $conjunction = '?'; + if (isset($options[self::OSS_SUB_RESOURCE])) { + $resource_uri .= $conjunction . $options[self::OSS_SUB_RESOURCE]; + } + return $resource_uri; } /** - * generates query string + * Generates the signalbe query string parameters in array type * - * @param mixed $options - * @return string + * @param array $options + * @return array */ - private function generateQueryString($options) + private function generateSignableQueryStringParam($options) { - //query parameters - $query = array(); - $queryList = array( + $signableQueryStringParams = array(); + $signableList = array( self::OSS_PART_NUM, 'response-content-type', 'response-content-language', @@ -3384,19 +3330,89 @@ class OssClient self::OSS_CONTINUATION_TOKEN, self::OSS_CNAME, ); - foreach ($queryList as $item) { + + foreach ($signableList as $item) { if (isset($options[$item])) { - $query[$item] = $options[$item]; + $signableQueryStringParams[$item] = $options[$item]; } } - if (isset($options[self::OSS_QUERY_STRING])) { - $query = array_merge($query, $options[self::OSS_QUERY_STRING]); - } - if (isset($options[self::OSS_SUB_RESOURCE])) { - $query[$options[self::OSS_SUB_RESOURCE]] = ''; + + if ($this->enableStsInUrl && (!is_null($this->securityToken))) { + $signableQueryStringParams["security-token"] = $this->securityToken; } - return OssUtil::toQueryString($query); + return $signableQueryStringParams; + } + + /** + * Generates the resource uri for signing + * + * @param mixed $options + * @return string + */ + private function generateSignableResource($options) + { + $signableResource = ""; + $signableResource .= '/'; + if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) { + $signableResource .= $options[self::OSS_BUCKET]; + // if there's no object in options, adding a '/' if the host type is not IP.\ + if ($options[self::OSS_OBJECT] == '/') { + if ($this->hostType !== self::OSS_HOST_TYPE_IP) { + $signableResource .= "/"; + } + } + } + //signable_resource + object + if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) { + $signableResource .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT])); + } + if (isset($options[self::OSS_SUB_RESOURCE])) { + $signableResource .= '?' . $options[self::OSS_SUB_RESOURCE]; + } + return $signableResource; + } + + /** + * generates query string + * + * @param mixed $options + * @return string + */ + private function generateQueryString($options) + { + //query parameters + $queryStringParams = array(); + if (isset($options[self::OSS_QUERY_STRING])) { + $queryStringParams = array_merge($queryStringParams, $options[self::OSS_QUERY_STRING]); + } + return OssUtil::toQueryString($queryStringParams); + } + + private function stringToSignSorted($string_to_sign) + { + $queryStringSorted = ''; + $explodeResult = explode('?', $string_to_sign); + $index = count($explodeResult); + if ($index === 1) + return $string_to_sign; + + $queryStringParams = explode('&', $explodeResult[$index - 1]); + sort($queryStringParams); + + foreach($queryStringParams as $params) + { + $queryStringSorted .= $params . '&'; + } + + $queryStringSorted = substr($queryStringSorted, 0, -1); + + $result = ''; + for ($i = 0; $i < $index -1; $i++) + { + $result .= $explodeResult[$i] . '?'; + } + return $result . $queryStringSorted; } /** @@ -3408,24 +3424,20 @@ class OssClient */ private function generateHeaders($options, $hostname) { - $headers = array(); - - if (!empty($hostname)) { - $headers[self::OSS_HOST] = $hostname; - } - - if (isset($options[self::OSS_CONTENT_TYPE])) { - $headers[self::OSS_CONTENT_TYPE] = $options[self::OSS_CONTENT_TYPE]; - } - - if (isset($options[self::OSS_DATE])) { - $headers[self::OSS_DATE] = $options[self::OSS_DATE]; - } - + $headers = array( + self::OSS_CONTENT_MD5 => '', + self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : self::DEFAULT_CONTENT_TYPE, + self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \G\M\T'), + self::OSS_HOST => $hostname, + ); if (isset($options[self::OSS_CONTENT_MD5])) { $headers[self::OSS_CONTENT_MD5] = $options[self::OSS_CONTENT_MD5]; } + //Add stsSecurityToken + if ((!is_null($this->securityToken)) && (!$this->enableStsInUrl)) { + $headers[self::OSS_SECURITY_TOKEN] = $this->securityToken; + } //Merge HTTP headers if (isset($options[self::OSS_HEADERS])) { $headers = array_merge($headers, $options[self::OSS_HEADERS]); @@ -3450,7 +3462,6 @@ class OssClient * @param string $endpoint * @param boolean $isCName * @return string The domain name without the protocol schema. - * @throws OssException */ private function checkEndpoint($endpoint, $isCName) { @@ -3476,110 +3487,6 @@ class OssClient return $ret_endpoint; } - /** - * @param Credentials $credential - * @throws OssException - */ - private function checkCredentials($credential) - { - if (empty($credential)) { - throw new OssException("credentials is empty."); - } - if (strlen($credential->getAccessKeyId()) == 0) { - throw new OssException("access key id is empty"); - } - if (strlen($credential->getAccessKeySecret()) == 0) { - throw new OssException("access key secret is empty"); - } - } - - /** - * For get Sign Product - * @return string - */ - private function getProduct() - { - if (!empty($this->cloudBoxId)) { - return self::OSS_CLOUDBOX_PRODUCT; - } - return self::OSS_DEFAULT_PRODUCT; - } - - /** - * For get Sign Region - * @return mixed - */ - private function getRegion() - { - if (!empty($this->cloudBoxId)) { - return $this->cloudBoxId; - } - return $this->region; - } - - /** - * Encodes the file path from UTF-8 to GBK. - * - * @param $filepath - * @return string - */ - private function encodeFilePath($filepath) - { - if ($this->filePathCompatible !== true) { - return $filepath; - } - - if (empty($filepath)) { - return $filepath; - } - - try { - $encoding = array('UTF-8', 'GB2312', 'GBK'); - $encode = mb_detect_encoding($filepath, $encoding); - if ($encode !== 'UTF-8') { - return $filepath; - } - $tmp = iconv($encode, 'GBK', $filepath); - if ($tmp !== false) { - $filepath = $tmp; - } - } catch (\Exception $e) { - //IGNORE - } - return $filepath; - } - - /** - * Decodes the file path from GBK to UTF-8. - * - * @param $filepath - * @return string - */ - private function decodeFilePath($filepath) - { - if ($this->filePathCompatible !== true) { - return $filepath; - } - if (empty($filepath)) { - return $filepath; - } - - try { - $encoding = array('UTF-8', 'GB2312', 'GBK'); - $encode = mb_detect_encoding($filepath, $encoding); - if ($encode === 'UTF-8' || $encode === false) { - return $filepath; - } - $tmp = iconv($encode, 'UTF-8', $filepath); - if ($tmp !== false) { - $filepath = $tmp; - } - } catch (\Exception $e) { - //IGNORE - } - return $filepath; - } - /** * Check if all dependent extensions are installed correctly. * For now only "curl" is needed. @@ -3633,7 +3540,6 @@ class OssClient const OSS_BUCKET = 'bucket'; const OSS_OBJECT = 'object'; const OSS_HEADERS = OssUtil::OSS_HEADERS; - const OSS_ADDITIONAL_HEADERS = 'additionalHeaders'; const OSS_METHOD = 'method'; const OSS_QUERY = 'query'; const OSS_BASENAME = 'basename'; @@ -3668,7 +3574,7 @@ class OssClient const OSS_IF_NONE_MATCH = 'If-None-Match'; const OSS_CACHE_CONTROL = 'Cache-Control'; const OSS_EXPIRES = 'Expires'; - + const OSS_PREAUTH = 'preauth'; const OSS_CONTENT_COING = 'Content-Coding'; const OSS_CONTENT_DISPOSTION = 'Content-Disposition'; const OSS_RANGE = 'range'; @@ -3690,7 +3596,6 @@ class OssClient const OSS_SUB_RESOURCE = 'sub_resource'; const OSS_DEFAULT_PREFIX = 'x-oss-'; const OSS_CHECK_MD5 = 'checkmd5'; - const OSS_CHECK_OBJECT = 'checkobject'; const DEFAULT_CONTENT_TYPE = 'application/octet-stream'; const OSS_SYMLINK_TARGET = 'x-oss-symlink-target'; const OSS_SYMLINK = 'symlink'; @@ -3743,7 +3648,7 @@ class OssClient const OSS_ACL_TYPE_PUBLIC_READ_WRITE = 'public-read-write'; const OSS_ENCODING_TYPE = "encoding-type"; const OSS_ENCODING_TYPE_URL = "url"; - + const OSS_LIST_TYPE = "list-type"; // Domain Types @@ -3751,7 +3656,6 @@ class OssClient const OSS_HOST_TYPE_IP = "ip"; //http://1.1.1.1/bucket/object const OSS_HOST_TYPE_SPECIAL = 'special'; //http://bucket.guizhou.gov/object const OSS_HOST_TYPE_CNAME = "cname"; //http://mydomain.com/object - const OSS_HOST_TYPE_PATH_STYLE = "path-style"; //http://oss-cn-hangzhou.aliyuncs.com/bucket/object //OSS ACL array static $OSS_ACL_TYPES = array( self::OSS_ACL_TYPE_PRIVATE, @@ -3760,19 +3664,13 @@ class OssClient ); // OssClient version information const OSS_NAME = "aliyun-sdk-php"; - const OSS_VERSION = "2.7.2"; - const OSS_BUILD = "20241028"; + const OSS_VERSION = "2.5.0"; + const OSS_BUILD = "20220513"; const OSS_AUTHOR = ""; const OSS_OPTIONS_ORIGIN = 'Origin'; const OSS_OPTIONS_REQUEST_METHOD = 'Access-Control-Request-Method'; const OSS_OPTIONS_REQUEST_HEADERS = 'Access-Control-Request-Headers'; - // signatrue version information - const OSS_SIGNATURE_VERSION_V1 = "v1"; - const OSS_SIGNATURE_VERSION_V4 = "v4"; - const OSS_DEFAULT_PRODUCT = "oss"; - const OSS_CLOUDBOX_PRODUCT = "oss-cloudbox"; - //use ssl flag private $useSSL = false; private $maxRetries = 3; @@ -3781,22 +3679,11 @@ class OssClient // user's domain type. It could be one of the four: OSS_HOST_TYPE_NORMAL, OSS_HOST_TYPE_IP, OSS_HOST_TYPE_SPECIAL, OSS_HOST_TYPE_CNAME private $hostType = self::OSS_HOST_TYPE_NORMAL; private $requestProxy = null; - /** - * @var CredentialsProvider - */ - private $provider; + private $accessKeyId; + private $accessKeySecret; private $hostname; - private $enableStrictObjName; + private $securityToken; + private $enableStsInUrl = false; private $timeout = 0; private $connectTimeout = 0; - private $cloudBoxId = null; - private $region = null; - /** - * @var SignerV1|SignerV4 - */ - private $signer; - - private $checkObjectEncoding = false; - - private $filePathCompatible; } diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/CreateBucketCnameTokenResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/CreateBucketCnameTokenResult.php index a38ca0d51..74bcb8dc4 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/CreateBucketCnameTokenResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/CreateBucketCnameTokenResult.php @@ -7,7 +7,7 @@ use OSS\Model\CnameTokenInfo; class CreateBucketCnameTokenResult extends Result { /** - * @return CnameTokenInfo + * @return CnameConfig */ protected function parseDataFromResponse() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetBucketInfoResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetBucketInfoResult.php index d467851cb..ad55e95bc 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetBucketInfoResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetBucketInfoResult.php @@ -16,7 +16,7 @@ class GetBucketInfoResult extends Result /** * Parse data from response * - * @return BucketInfo + * @return string * @throws OssException */ protected function parseDataFromResponse() diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelHistoryResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelHistoryResult.php index 5d5bc927d..202a6681d 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelHistoryResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelHistoryResult.php @@ -7,7 +7,7 @@ use OSS\Model\GetLiveChannelHistory; class GetLiveChannelHistoryResult extends Result { /** - * @return GetLiveChannelHistory + * @return */ protected function parseDataFromResponse() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelInfoResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelInfoResult.php index cefe460ab..d5a9005e7 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelInfoResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/GetLiveChannelInfoResult.php @@ -7,7 +7,7 @@ use OSS\Model\GetLiveChannelInfo; class GetLiveChannelInfoResult extends Result { /** - * @return GetLiveChannelInfo + * @return */ protected function parseDataFromResponse() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectVersionsResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectVersionsResult.php index 4503c03d0..849c21c29 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectVersionsResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectVersionsResult.php @@ -2,7 +2,6 @@ namespace OSS\Result; -use OSS\Core\OssException; use OSS\Core\OssUtil; use OSS\Model\ObjectVersionInfo; use OSS\Model\ObjectVersionListInfo; @@ -18,12 +17,11 @@ class ListObjectVersionsResult extends Result /** * Parse the xml data returned by the ListObjectVersions interface * - * @return ObjectVersionListInfo - * @throws OssException + * return ObjectVersionListInfo */ protected function parseDataFromResponse() { - $xml = simplexml_load_string($this->rawResponse->body); + $xml = simplexml_load_string($this->rawResponse->body); $encodingType = isset($xml->EncodingType) ? strval($xml->EncodingType) : ""; $objectVersionList = $this->parseObjecVersionList($xml, $encodingType); $deleteMarkerList = $this->parseDeleteMarkerList($xml, $encodingType); @@ -42,8 +40,8 @@ class ListObjectVersionsResult extends Result $delimiter = OssUtil::decodeKey($delimiter, $encodingType); $isTruncated = isset($xml->IsTruncated) ? strval($xml->IsTruncated) : ""; - return new ObjectVersionListInfo($bucketName, $prefix, $keyMarker, $nextKeyMarker, - $versionIdMarker, $nextVersionIdMarker, $maxKeys, $delimiter, $isTruncated, + return new ObjectVersionListInfo($bucketName, $prefix, $keyMarker, $nextKeyMarker, + $versionIdMarker, $nextVersionIdMarker,$maxKeys, $delimiter, $isTruncated, $objectVersionList, $deleteMarkerList, $prefixList); } diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsResult.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsResult.php index 124617457..39f1f2927 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsResult.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsResult.php @@ -2,11 +2,9 @@ namespace OSS\Result; -use OSS\Core\OssException; use OSS\Core\OssUtil; use OSS\Model\ObjectInfo; use OSS\Model\ObjectListInfo; -use OSS\Model\Owner; use OSS\Model\PrefixInfo; /** @@ -18,8 +16,7 @@ class ListObjectsResult extends Result /** * Parse the xml data returned by the ListObjects interface * - * @return ObjectListInfo - * @throws OssException + * return ObjectListInfo */ protected function parseDataFromResponse() { @@ -53,13 +50,7 @@ class ListObjectsResult extends Result $type = isset($content->Type) ? strval($content->Type) : ""; $size = isset($content->Size) ? strval($content->Size) : "0"; $storageClass = isset($content->StorageClass) ? strval($content->StorageClass) : ""; - if(isset($content->Owner)){ - $owner = new Owner(strval($content->Owner->ID),strval($content->Owner->DisplayName)); - }else{ - $owner = null; - } - $restoreInfo= isset($content->RestoreInfo) ? strval($content->RestoreInfo) : null; - $retList[] = new ObjectInfo($key, $lastModified, $eTag, $type, $size, $storageClass,$owner,$restoreInfo); + $retList[] = new ObjectInfo($key, $lastModified, $eTag, $type, $size, $storageClass); } } return $retList; diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsV2Result.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsV2Result.php index 8293767d8..882c3c0e3 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsV2Result.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/ListObjectsV2Result.php @@ -2,11 +2,9 @@ namespace OSS\Result; -use OSS\Core\OssException; use OSS\Core\OssUtil; use OSS\Model\ObjectInfo; use OSS\Model\ObjectListInfoV2; -use OSS\Model\Owner; use OSS\Model\PrefixInfo; /** @@ -18,8 +16,7 @@ class ListObjectsV2Result extends Result /** * Parse the xml data returned by the ListObjectsV2 interface * - * @return ObjectListInfoV2 - * @throws OssException + * return ObjectListInfoV2 */ protected function parseDataFromResponse() { @@ -37,7 +34,7 @@ class ListObjectsV2Result extends Result $continuationToken = isset($xml->ContinuationToken) ? strval($xml->ContinuationToken) : ""; $nextContinuationToken = isset($xml->NextContinuationToken) ? strval($xml->NextContinuationToken) : ""; $startAfter = isset($xml->StartAfter) ? strval($xml->StartAfter) : ""; - $startAfter = OssUtil::decodeKey($startAfter, $encodingType); + $startAfter = OssUtil::decodeKey($startAfter, $encodingType); $keyCount = isset($xml->KeyCount) ? intval($xml->KeyCount) : 0; return new ObjectListInfoV2($bucketName, $prefix, $maxKeys, $delimiter, $isTruncated, $objectList, $prefixList, $continuationToken, $nextContinuationToken, $startAfter, $keyCount); } @@ -54,13 +51,7 @@ class ListObjectsV2Result extends Result $type = isset($content->Type) ? strval($content->Type) : ""; $size = isset($content->Size) ? strval($content->Size) : "0"; $storageClass = isset($content->StorageClass) ? strval($content->StorageClass) : ""; - if(isset($content->Owner)){ - $owner = new Owner(strval($content->Owner->ID),strval($content->Owner->DisplayName)); - }else{ - $owner = null; - } - $restoreInfo= isset($content->RestoreInfo) ? strval($content->RestoreInfo) : null; - $retList[] = new ObjectInfo($key, $lastModified, $eTag, $type, $size, $storageClass,$owner,$restoreInfo); + $retList[] = new ObjectInfo($key, $lastModified, $eTag, $type, $size, $storageClass); } } return $retList; diff --git a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/Result.php b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/Result.php index 597ac5a6b..e5d83d377 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/Result.php +++ b/src/vendor/aliyuncs/oss-sdk-php/src/OSS/Result/Result.php @@ -109,29 +109,10 @@ abstract class Result if (empty($body) || false === strpos($body, 'Message)) { - return strval($xml->Message); - } - $flag = true; - } catch (\Exception $e) { - $flag = true; + $xml = simplexml_load_string($body); + if (isset($xml->Message)) { + return strval($xml->Message); } - if ($flag === true) { - $start = strpos($body, ''); - if ($start === false) { - return ''; - } - $start += 9; - $end = strpos($body, '', $start); - if ($end === false) { - return ''; - } - return substr($body, $start, $end - $start); - } - return ''; } @@ -146,29 +127,10 @@ abstract class Result if (empty($body) || false === strpos($body, 'Code)) { - return strval($xml->Code); - } - $flag = true; - } catch (\Exception $e) { - $flag = true; + $xml = simplexml_load_string($body); + if (isset($xml->Code)) { + return strval($xml->Code); } - if ($flag === true) { - $start = strpos($body, ''); - if ($start === false) { - return ''; - } - $start += 6; - $end = strpos($body, '', $start); - if ($end === false) { - return ''; - } - return substr($body, $start, $end - $start); - } - return ''; } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketCnameTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketCnameTest.php index 290f58529..03b016f49 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketCnameTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketCnameTest.php @@ -4,7 +4,6 @@ namespace OSS\Tests; require_once __DIR__ . '/Common.php'; -use OSS\Core\OssException; use OSS\Model\CnameConfig; class BucketCnameTest extends \PHPUnit\Framework\TestCase @@ -32,34 +31,47 @@ class BucketCnameTest extends \PHPUnit\Framework\TestCase public function testAddCname() { - try { - $this->client->addBucketCname($this->bucketName, 'www.baidu.com'); - } catch (OssException $e) { - print_r($e->getMessage()); - $this->assertTrue(true); - } + $this->client->addBucketCname($this->bucketName, 'www.baidu.com'); + $this->client->addBucketCname($this->bucketName, 'www.qq.com'); - try { - $ret = $this->client->getBucketCname($this->bucketName); - $this->assertEquals(0, count($ret->getCnames())); - } catch (OssException $e) { - $this->assertTrue(false); + $ret = $this->client->getBucketCname($this->bucketName); + $this->assertEquals(2, count($ret->getCnames())); + + // add another 2 cnames + $this->client->addBucketCname($this->bucketName, 'www.sina.com.cn'); + $this->client->addBucketCname($this->bucketName, 'www.iqiyi.com'); + + $ret = $this->client->getBucketCname($this->bucketName); + $cnames = $ret->getCnames(); + $cnameList = array(); + + foreach ($cnames as $c) { + $cnameList[] = $c['Domain']; } + $should = array( + 'www.baidu.com', + 'www.qq.com', + 'www.sina.com.cn', + 'www.iqiyi.com' + ); + $this->assertEquals(4, count($cnames)); + $this->assertEquals(sort($should), sort($cnameList)); } public function testDeleteCname() { - try { - $this->client->deleteBucketCname($this->bucketName, 'www.not-exist.com'); - } catch (OssException $e) { - $this->assertTrue(false); - } + $this->client->addBucketCname($this->bucketName, 'www.baidu.com'); + $this->client->addBucketCname($this->bucketName, 'www.qq.com'); - try { - $ret = $this->client->getBucketCname($this->bucketName); - $this->assertEquals(0, count($ret->getCnames())); - } catch (OssException $e) { - $this->assertTrue(false); - } + $ret = $this->client->getBucketCname($this->bucketName); + $this->assertEquals(2, count($ret->getCnames())); + + // delete one cname + $this->client->deleteBucketCname($this->bucketName, 'www.baidu.com'); + + $ret = $this->client->getBucketCname($this->bucketName); + $this->assertEquals(1, count($ret->getCnames())); + $cnames = $ret->getCnames(); + $this->assertEquals('www.qq.com', $cnames[0]['Domain']); } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketLiveChannelTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketLiveChannelTest.php index dacae0b80..cedf884d4 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketLiveChannelTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/BucketLiveChannelTest.php @@ -14,14 +14,10 @@ class BucketLiveChannelTest extends \PHPUnit\Framework\TestCase protected function setUp(): void { - try { - $this->client = Common::getOssClient(); - $this->bucketName = 'php-sdk-test-rtmp-bucket-name-' . strval(rand(0, 10000)); - $this->client->createBucket($this->bucketName); - Common::waitMetaSync(); - }catch(\Exception $e) { - - } + $this->client = Common::getOssClient(); + $this->bucketName = 'php-sdk-test-rtmp-bucket-name-' . strval(rand(0, 10000)); + $this->client->createBucket($this->bucketName); + Common::waitMetaSync(); } protected function tearDown(): void diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CallbackTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CallbackTest.php index feb080105..31df548d8 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CallbackTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CallbackTest.php @@ -44,26 +44,27 @@ class CallbackTest extends TestOssClientBase /** * step 3. */ - $json = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $json = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\"mimeType\":${mimeType},\"size\":${size},\"x:var1\":${x:var1},\"x:var2\":${x:var2}}", "callbackBodyType":"application/json" }'; - - $var = - '{ + + $var = + '{ "x:var1":"value1", "x:var2":"值2" }'; - $options = array(OssClient::OSS_CALLBACK => $json, - OssClient::OSS_CALLBACK_VAR => $var - ); + $options = array(OssClient::OSS_CALLBACK => $json, + OssClient::OSS_CALLBACK_VAR => $var + ); try { $result = $this->ossClient->completeMultipartUpload($this->bucket, $object, $upload_id, $upload_parts, $options); $this->assertEquals("200", $result['info']['http_code']); + $this->assertEquals("{\"Status\":\"OK\"}", $result['body']); } catch (OssException $e) { $this->assertTrue(false); } @@ -103,24 +104,24 @@ class CallbackTest extends TestOssClientBase /** * step 3. */ - - $json = - '{ + + $json = + '{ "callbackUrl":"www.baidu.com", "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\"mimeType\":${mimeType},\"size\":${size},\"x:var1\":${x:var1},\"x:var2\":${x:var2}}", "callbackBodyType":"application/json" }'; - - $var = - '{ + + $var = + '{ "x:var1":"value1", "x:var2":"值2" }'; - $options = array(OssClient::OSS_CALLBACK => $json, - OssClient::OSS_CALLBACK_VAR => $var - ); - + $options = array(OssClient::OSS_CALLBACK => $json, + OssClient::OSS_CALLBACK_VAR => $var + ); + try { $result = $this->ossClient->completeMultipartUpload($this->bucket, $object, $upload_id, $upload_parts, $options); $this->assertTrue(false); @@ -130,39 +131,39 @@ class CallbackTest extends TestOssClientBase } } - + public function testPutObjectCallbackNormal() { //json { - $json = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $json = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\"mimeType\":${mimeType},\"size\":${size}}", "callbackBodyType":"application/json" }'; $options = array(OssClient::OSS_CALLBACK => $json); $this->putObjectCallbackOk($options, "200"); - } - //url - { - $url = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + } + //url + { + $url = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}", "callbackBodyType":"application/x-www-form-urlencoded" }'; $options = array(OssClient::OSS_CALLBACK => $url); $this->putObjectCallbackOk($options, "200"); - } + } // Unspecified typre - { - $url = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + { + $url = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}" }'; $options = array(OssClient::OSS_CALLBACK => $url); @@ -170,10 +171,10 @@ class CallbackTest extends TestOssClientBase } //json and body is chinese { - $json = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $json = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\" 春水碧于天,画船听雨眠。\":\"垆边人似月,皓腕凝霜雪。\"}", "callbackBodyType":"application/json" }'; @@ -182,10 +183,10 @@ class CallbackTest extends TestOssClientBase } //url and body is chinese { - $url = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $url = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"春水碧于天,画船听雨眠。垆边人似月,皓腕凝霜雪", "callbackBodyType":"application/x-www-form-urlencoded" }'; @@ -194,51 +195,51 @@ class CallbackTest extends TestOssClientBase } //json and add callback_var { - $json = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $json = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\"mimeType\":${mimeType},\"size\":${size},\"x:var1\":${x:var1},\"x:var2\":${x:var2}}", "callbackBodyType":"application/json" }'; - - $var = - '{ + + $var = + '{ "x:var1":"value1", "x:var2":"aliyun.com" }'; $options = array(OssClient::OSS_CALLBACK => $json, - OssClient::OSS_CALLBACK_VAR => $var - ); + OssClient::OSS_CALLBACK_VAR => $var + ); $this->putObjectCallbackOk($options, "200"); } //url and add callback_var { - $url = - '{ - "callbackUrl":"' . Common::getCallbackUrl() . '",' . - ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", + $url = + '{ + "callbackUrl":"'.Common::getCallbackUrl().'",'. + ' "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}&my_var1=${x:var1}&my_var2=${x:var2}", "callbackBodyType":"application/x-www-form-urlencoded" }'; - $var = - '{ + $var = + '{ "x:var1":"value1凌波不过横塘路,但目送,芳", "x:var2":"值2" }'; $options = array(OssClient::OSS_CALLBACK => $url, - OssClient::OSS_CALLBACK_VAR => $var - ); + OssClient::OSS_CALLBACK_VAR => $var + ); $this->putObjectCallbackOk($options, "200"); } } public function testPutCallbackWithCallbackFailed() - { + { { - $json = - '{ + $json = + '{ "callbackUrl":"http://www.baidu.com", "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"{\"mimeType\":${mimeType},\"size\":${size}}", @@ -249,13 +250,13 @@ class CallbackTest extends TestOssClientBase } { - $url = - '{ + $url = + '{ "callbackUrl":"http://www.baidu.com", "callbackHost":"oss-cn-hangzhou.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}&my_var1=${x:var1}&my_var2=${x:var2}", "callbackBodyType":"application/x-www-form-urlencoded" - }'; + }'; $options = array(OssClient::OSS_CALLBACK => $url); $this->putObjectCallbackFailed($options, "203"); } @@ -269,6 +270,7 @@ class CallbackTest extends TestOssClientBase try { $result = $this->ossClient->putObject($this->bucket, $object, $content, $options); $this->assertEquals($status, $result['info']['http_code']); + $this->assertEquals("{\"Status\":\"OK\"}", $result['body']); } catch (OssException $e) { $this->assertFalse(true); } @@ -290,8 +292,5 @@ class CallbackTest extends TestOssClientBase protected function setUp(): void { parent::setUp(); - if (strlen(Common::getCallbackUrl()) == 0) { - throw new OssException("callback url can not be empty!"); - } } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/Common.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/Common.php index 5b76a76a4..152894481 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/Common.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/Common.php @@ -3,11 +3,9 @@ namespace OSS\Tests; require_once __DIR__ . '/../../../autoload.php'; -require_once __DIR__ . DIRECTORY_SEPARATOR . 'StsClient.php'; use OSS\OssClient; use OSS\Core\OssException; -use OSS\Credentials\StaticCredentialsProvider; /** * Class Common @@ -21,121 +19,34 @@ class Common * * @return OssClient An OssClient instance */ - public static function getOssClient($conf = NULL) + public static function getOssClient() { try { - $provider = new StaticCredentialsProvider( - getenv('OSS_ACCESS_KEY_ID'), - getenv('OSS_ACCESS_KEY_SECRET') - ); - $config = array( - 'region' => self::getRegion(), - 'endpoint' => self::getEndpoint(), - 'provider' => $provider, - 'signatureVersion' => self::getSignVersion() - ); - - if ($conf != null) { - foreach ($conf as $key => $value) { - $config[$key] = $value; - } - } - - $ossClient = new OssClient($config); - - } catch (OssException $e) { - printf(__FUNCTION__ . "creating OssClient instance: FAILED\n"); - printf($e->getMessage() . "\n"); - } - return $ossClient; - } - - public static function getStsOssClient($conf = NULL) - { - $stsClient = new StsClient(); - $assumeRole = new AssumeRole(); - $stsClient->AccessSecret = getenv('OSS_ACCESS_KEY_SECRET'); - $assumeRole->AccessKeyId = getenv('OSS_ACCESS_KEY_ID'); - $assumeRole->RoleArn = getenv('OSS_TEST_RAM_ROLE_ARN'); - $params = $assumeRole->getAttributes(); - $response = $stsClient->doAction($params); - - try { - $provider = new StaticCredentialsProvider( - $response->Credentials->AccessKeyId, - $response->Credentials->AccessKeySecret, - $response->Credentials->SecurityToken - ); - $config = array( - 'region' => self::getRegion(), - 'endpoint' => self::getEndpoint(), - 'provider' => $provider, - 'signatureVersion' => self::getSignVersion() - ); - - if ($conf != null) { - foreach ($conf as $key => $value) { - $config[$key] = $value; - } - } - - $ossStsClient = new OssClient($config); - + $ossClient = new OssClient( + getenv('OSS_ACCESS_KEY_ID'), + getenv('OSS_ACCESS_KEY_SECRET'), + getenv('OSS_ENDPOINT'), false); } catch (OssException $e) { printf(__FUNCTION__ . "creating OssClient instance: FAILED\n"); printf($e->getMessage() . "\n"); return null; } - return $ossStsClient; + return $ossClient; } public static function getBucketName() { - $name = getenv('OSS_BUCKET'); - if (empty($name)) { - return "skyranch-php-test"; - } - return $name; + return getenv('OSS_BUCKET'); } public static function getRegion() { - return getenv('OSS_TEST_REGION'); - } - - public static function getEndpoint() - { - return getenv('OSS_TEST_ENDPOINT'); + return getenv('OSS_REGION'); } public static function getCallbackUrl() { - return getenv('OSS_TEST_CALLBACK_URL'); - } - - public static function getPayerUid() - { - return getenv('OSS_TEST_PAYER_UID'); - } - - public static function getPayerAccessKeyId() - { - return getenv('OSS_TEST_PAYER_ACCESS_KEY_ID'); - } - - public static function getPayerAccessKeySecret() - { - return getenv('OSS_TEST_PAYER_ACCESS_KEY_SECRET'); - } - - public static function getSignVersion() - { - return OssClient::OSS_SIGNATURE_VERSION_V1; - } - - public static function getPathStyleBucket() - { - return getenv('OSS_TEST_PATHSTYLE_BUCKET'); + return getenv('OSS_CALLBACK_URL'); } /** diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ContentTypeTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ContentTypeTest.php index 98c59981b..66b405775 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ContentTypeTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ContentTypeTest.php @@ -2,14 +2,19 @@ namespace OSS\Tests; -use OSS\Core\OssUtil; -use OSS\OssClient; - require_once __DIR__ . '/Common.php'; -require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestOssClientBase.php'; class ContentTypeTest extends TestOssClientBase { + private function runCmd($cmd) + { + $output = array(); + $status = 0; + exec($cmd . ' 2>/dev/null', $output, $status); + + $this->assertEquals(0, $status); + } + private function getContentType($bucket, $object) { $client = $this->ossClient; @@ -22,22 +27,22 @@ class ContentTypeTest extends TestOssClientBase $client = $this->ossClient; $bucket = $this->bucket; - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.html'; + $file = '/tmp/x.html'; $object = 'test/x'; - OssUtil::generateFile($file, 5); + $this->runCmd('touch ' . $file); $client->uploadFile($bucket, $object, $file); $type = $this->getContentType($bucket, $object); - $this->assertEquals('text/html', $type); - unlink($file); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.json'; + $this->assertEquals('text/html', $type); + + $file = '/tmp/x.json'; $object = 'test/y'; - OssUtil::generateFile($file, 100 * 1024); + $this->runCmd('dd if=/dev/urandom of=' . $file . ' bs=1024 count=100'); $client->multiuploadFile($bucket, $object, $file, array('partSize' => 100)); $type = $this->getContentType($bucket, $object); - unlink($file); + $this->assertEquals('application/json', $type); } @@ -49,37 +54,43 @@ class ContentTypeTest extends TestOssClientBase $object = "test/x.txt"; $client->putObject($bucket, $object, "hello world"); $type = $this->getContentType($bucket, $object); + $this->assertEquals('text/plain', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.html'; + $file = '/tmp/x.html'; $object = 'test/x.txt'; - OssUtil::generateFile($file, 5); + $this->runCmd('touch ' . $file); + $client->uploadFile($bucket, $object, $file); - unlink($file); $type = $this->getContentType($bucket, $object); + $this->assertEquals('text/html', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.none'; + $file = '/tmp/x.none'; $object = 'test/x.txt'; - OssUtil::generateFile($file, 5); + $this->runCmd('touch ' . $file); + $client->uploadFile($bucket, $object, $file); - unlink($file); $type = $this->getContentType($bucket, $object); + $this->assertEquals('text/plain', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.mp3'; - OssUtil::generateFile($file, 1024 * 100); + $file = '/tmp/x.mp3'; $object = 'test/y.json'; + $this->runCmd('dd if=/dev/urandom of=' . $file . ' bs=1024 count=100'); + $client->multiuploadFile($bucket, $object, $file, array('partSize' => 100)); - unlink($file); $type = $this->getContentType($bucket, $object); + $this->assertEquals('audio/mpeg', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.none'; - OssUtil::generateFile($file, 1024 * 100); + + $file = '/tmp/x.none'; $object = 'test/y.json'; + $this->runCmd('dd if=/dev/urandom of=' . $file . ' bs=1024 count=100'); + $client->multiuploadFile($bucket, $object, $file, array('partSize' => 100)); - unlink($file); $type = $this->getContentType($bucket, $object); + $this->assertEquals('application/json', $type); } @@ -96,28 +107,27 @@ class ContentTypeTest extends TestOssClientBase $this->assertEquals('text/html', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.html'; + $file = '/tmp/x.html'; $object = 'test/x'; - OssUtil::generateFile($file, 100); + $this->runCmd('touch ' . $file); - $client->uploadFile($bucket, $object, $file, array(OssClient::OSS_HEADERS => array( + $client->uploadFile($bucket, $object, $file, array( 'Content-Type' => 'application/json' - ))); - unlink($file); + )); $type = $this->getContentType($bucket, $object); $this->assertEquals('application/json', $type); - $file = __DIR__ . DIRECTORY_SEPARATOR . 'x.json'; + $file = '/tmp/x.json'; $object = 'test/y'; - OssUtil::generateFile($file, 100 * 1024); + $this->runCmd('dd if=/dev/urandom of=' . $file . ' bs=1024 count=100'); $client->multiuploadFile($bucket, $object, $file, array( 'partSize' => 100, 'Content-Type' => 'audio/mpeg' )); - unlink($file); $type = $this->getContentType($bucket, $object); + $this->assertEquals('audio/mpeg', $type); } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CorsConfigTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CorsConfigTest.php index 42a46fa8e..3329b1af8 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CorsConfigTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/CorsConfigTest.php @@ -3,12 +3,9 @@ namespace OSS\Tests; -use OSS\Http\ResponseCore; use OSS\Model\CorsConfig; use OSS\Model\CorsRule; use OSS\Core\OssException; -use OSS\Result\GetCorsResult; -use OSS\Result\Result; class CorsConfigTest extends \PHPUnit\Framework\TestCase { @@ -38,7 +35,6 @@ class CorsConfigTest extends \PHPUnit\Framework\TestCase x-oss-test1 110 -false BBBB; @@ -62,23 +58,6 @@ BBBB; 10 -BBBB; - - private $validXml3 = << - - -http://www.b.com -http://www.a.com -http://www.a.com -GET -PUT -POST -x-oss-test -10 - -true - BBBB; public function testParseValidXml() @@ -102,56 +81,6 @@ BBBB; $this->assertEquals($this->cleanXml($this->validXml2), $this->cleanXml($corsConfig->serializeToXml())); } - public function testParseValidXml3() - { - $corsConfig = new CorsConfig(); - $corsConfig->parseFromXml($this->validXml3); - $this->assertEquals($this->cleanXml($this->validXml3), $this->cleanXml($corsConfig->serializeToXml())); - $this->assertTrue($corsConfig->getResponseVary()); - } - - public function testResponseValidXml3() - { - $response = new ResponseCore(array(), $this->validXml, 200); - $result = new GetCorsResult($response); - $this->assertTrue($result->isOK()); - $this->assertNotNull($result->getData()); - $this->assertNotNull($result->getRawResponse()); - $this->assertNotNull($result->getRawResponse()->body); - $corsConfig = $result->getData(); - $this->assertEquals($this->cleanXml($this->validXml), $this->cleanXml($corsConfig->serializeToXml())); - $this->assertNotNull($corsConfig->getRules()); - $rules = $corsConfig->getRules(); - $this->assertNotNull($rules[0]->getAllowedHeaders()); - $this->assertNotNull($rules[0]->getAllowedMethods()); - $this->assertNotNull($rules[0]->getAllowedOrigins()); - $this->assertNotNull($rules[0]->getExposeHeaders()); - $this->assertNotNull($rules[0]->getMaxAgeSeconds()); - $this->assertFalse($corsConfig->getResponseVary()); - - } - - public function testResponseValidXml4() - { - $response = new ResponseCore(array(), $this->validXml3, 200); - $result = new GetCorsResult($response); - $this->assertTrue($result->isOK()); - $this->assertNotNull($result->getData()); - $this->assertNotNull($result->getRawResponse()); - $this->assertNotNull($result->getRawResponse()->body); - $corsConfig = $result->getData(); - $this->assertEquals($this->cleanXml($this->validXml3), $this->cleanXml($corsConfig->serializeToXml())); - $this->assertNotNull($corsConfig->getRules()); - $rules = $corsConfig->getRules(); - $this->assertNotNull($rules[0]->getAllowedHeaders()); - $this->assertNotNull($rules[0]->getAllowedMethods()); - $this->assertNotNull($rules[0]->getAllowedOrigins()); - $this->assertNotNull($rules[0]->getExposeHeaders()); - $this->assertNotNull($rules[0]->getMaxAgeSeconds()); - $this->assertTrue($corsConfig->getResponseVary()); - - } - public function testCreateCorsConfigFromMoreThan10Rules() { $corsConfig = new CorsConfig(); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/DeleteObjectVersionsResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/DeleteObjectVersionsResultTest.php index 2419e55e5..890b1a5d6 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/DeleteObjectVersionsResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/DeleteObjectVersionsResultTest.php @@ -10,79 +10,79 @@ class DeleteObjectVersionsResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - - - demo.jpg - CAEQNRiBgICEoPiC0BYiIGMxZWJmYmMzYjE0OTQ0ZmZhYjgzNzkzYjc2NjZk**** - true - 111111 - - -BBBB; + + + + demo.jpg + CAEQNRiBgICEoPiC0BYiIGMxZWJmYmMzYjE0OTQ0ZmZhYjgzNzkzYjc2NjZk**** + true + 111111 + + + BBBB; private $validXml1 = << - - - multipart.data - CAEQNRiBgIDyz.6C0BYiIGQ2NWEwNmVhNTA3ZTQ3MzM5ODliYjM1ZTdjYjA4**** - - -BBBB; + + + + multipart.data + CAEQNRiBgIDyz.6C0BYiIGQ2NWEwNmVhNTA3ZTQ3MzM5ODliYjM1ZTdjYjA4**** + + + BBBB; private $validXml2 = << - - - multipart.data - true - CAEQMhiBgIDXiaaB0BYiIGQzYmRkZGUxMTM1ZDRjOTZhNjk4YjRjMTAyZjhl**** - - - test.jpg - true - CAEQMhiBgIDB3aWB0BYiIGUzYTA3YzliMzVmNzRkZGM5NjllYTVlMjYyYWEy**** - - -BBBB; + + + + multipart.data + true + CAEQMhiBgIDXiaaB0BYiIGQzYmRkZGUxMTM1ZDRjOTZhNjk4YjRjMTAyZjhl**** + + + test.jpg + true + CAEQMhiBgIDB3aWB0BYiIGUzYTA3YzliMzVmNzRkZGM5NjllYTVlMjYyYWEy**** + + + BBBB; private $validXml3 = << - - - multipart.data - - - test.jpg - - - demo.jpg - - -BBBB; + + + + multipart.data + + + test.jpg + + + demo.jpg + + + BBBB; private $validXml4 = << - - url - - multipart%2F.data - - - test%2F.jpg - - - demo%2F.jpg - - -BBBB; - + + + url + + multipart%2F.data + + + test%2F.jpg + + + demo%2F.jpg + + + BBBB; + private $invalidXml = << - - -BBBB; + + + + BBBB; public function testParseValidXml() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketEncryptionResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketEncryptionResultTest.php index 87e499674..6f0e0d279 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketEncryptionResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketEncryptionResultTest.php @@ -10,39 +10,39 @@ class GetBucketEncryptionResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - - - AES256 - - - -BBBB; + + + + AES256 + + + + BBBB; private $validXml1 = << - - - KMS - kms-id - - -BBBB; + + + + KMS + kms-id + + + BBBB; private $validXml2 = << - - -KMS - - -BBBB; + + + + KMS + + + BBBB; private $invalidXml = << - - -BBBB; + + + + BBBB; public function testParseValidXml() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketRequestPaymentResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketRequestPaymentResultTest.php index 227028b90..2de08be6d 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketRequestPaymentResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketRequestPaymentResultTest.php @@ -10,24 +10,24 @@ class GetBucketRequestPaymentResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - - Requester - -BBBB; - + + + Requester + + BBBB; + private $validXml2 = << - - BucketOwner - -BBBB; + + + BucketOwner + + BBBB; private $invalidXml = << - - -BBBB; + + + + BBBB; public function testParseValidXml() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketStatResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketStatResultTest.php index 74cb04ab7..967e65d13 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketStatResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketStatResultTest.php @@ -9,33 +9,20 @@ use OSS\Http\ResponseCore; class GetBucketStatResultTest extends \PHPUnit\Framework\TestCase { -private $validXml = << - - 1600 - 230 - 40 - 4 - 1643341269 - 430 - 66 - 2359296 - 360 - 54 - 2949120 - 450 - 74 - 2359296 - 360 - 36 - -BBBB; + private $validXml = << + + 100 + 200 + 10 + + BBBB; -private $invalidXml = << - - -BBBB; + private $invalidXml = << + + + BBBB; public function testParseValidXml() { @@ -45,22 +32,9 @@ BBBB; $this->assertNotNull($result->getData()); $this->assertNotNull($result->getRawResponse()); $stat = $result->getData(); - $this->assertEquals(1600, $stat->getStorage()); - $this->assertEquals(230, $stat->getObjectCount()); - $this->assertEquals(40, $stat->getMultipartUploadCount()); - $this->assertEquals(4, $stat->getLiveChannelCount()); - $this->assertEquals(1643341269, $stat->getLastModifiedTime()); - $this->assertEquals(430, $stat->getStandardStorage()); - $this->assertEquals(66, $stat->getStandardObjectCount()); - $this->assertEquals(2359296, $stat->getInfrequentAccessStorage()); - $this->assertEquals(360, $stat->getInfrequentAccessRealStorage()); - $this->assertEquals(54, $stat->getInfrequentAccessObjectCount()); - $this->assertEquals(2949120, $stat->getArchiveStorage()); - $this->assertEquals(450, $stat->getArchiveRealStorage()); - $this->assertEquals(74, $stat->getArchiveObjectCount()); - $this->assertEquals(2359296, $stat->getColdArchiveStorage()); - $this->assertEquals(360, $stat->getColdArchiveRealStorage()); - $this->assertEquals(36, $stat->getColdArchiveObjectCount()); + $this->assertEquals(100, $stat->getStorage()); + $this->assertEquals(200, $stat->getObjectCount()); + $this->assertEquals(10, $stat->getMultipartUploadCount()); } public function testParseNullXml() diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketTagsResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketTagsResultTest.php index b2923092a..f4b2a8895 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketTagsResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketTagsResultTest.php @@ -9,34 +9,34 @@ use OSS\Http\ResponseCore; class GetBucketTagsResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - - - - testa - value1-test - - - testb - value2-test - - - -BBBB; + + + + + testa + value1-test + + + testb + value2-test + + + + BBBB; private $invalidXml = << - - -BBBB; + + + + BBBB; private $invalidXml2 = << - - - - -BBBB; + + + + + + BBBB; public function testParseValidXml() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketWormResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketWormResultTest.php index 3bb90daa7..4d5d91297 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketWormResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/GetBucketWormResultTest.php @@ -10,30 +10,30 @@ class GetBucketWormResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - -ID1 -Locked -1 -2018-08-14T15:50:32 - -BBBB; - - private $validXml2 = << - - ID2 - InProgress - 10 - 2018-09-14T15:50:32 - -BBBB; + + + ID1 + Locked + 1 + 2018-08-14T15:50:32 + + BBBB; + + private $validXml2 = << + + ID2 + InProgress + 10 + 2018-09-14T15:50:32 + + BBBB; private $invalidXml = << - - -BBBB; + + + + BBBB; public function testParseValidXml() { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListBucketsResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListBucketsResultTest.php index 959b0114e..634f97d3a 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListBucketsResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListBucketsResultTest.php @@ -42,53 +42,6 @@ BBBB; BBBB; - - private $errorBody = <<< BBBB - - - NoSuchBucket - The specified bucket does not exist. - 566B870D207FB3044302EB0A - hello.oss-test.aliyun-inc.com - hello - -BBBB; - - private $xml = << - - - ut_test_put_bucket - ut_test_put_bucket - - - - 2015-12-17T18:12:43.000Z - oss-cn-shanghai.aliyuncs.com - oss-cn-shanghai-internal.aliyuncs.com - oss-cn-shanghai - app-base-oss - cn-shanghai - Standard - - - 2014-12-25T11:21:04.000Z - oss-cn-hangzhou.aliyuncs.com - oss-cn-hangzhou-internal.aliyuncs.com - oss-cn-hangzhou - atestleo23 - cn-hangzhou - IA - - - 2014-12-25T11:21:04.000Z - oss-cn-hangzhou - atestleo23 - - - -BBBB; - public function testParseValidXml() { $response = new ResponseCore(array(), $this->validXml, 200); @@ -116,7 +69,18 @@ BBBB; $errorHeader = array( 'x-oss-request-id' => '1a2b-3c4d' ); - $response = new ResponseCore($errorHeader, $this->errorBody, 403); + + $errorBody = <<< BBBB + + + NoSuchBucket + The specified bucket does not exist. + 566B870D207FB3044302EB0A + hello.oss-test.aliyun-inc.com + hello + + BBBB; + $response = new ResponseCore($errorHeader, $errorBody, 403); try { new ListBucketsResult($response); } catch (OssException $e) { @@ -127,13 +91,48 @@ BBBB; $this->assertEquals($e->getRequestId(), '1a2b-3c4d'); $this->assertEquals($e->getErrorCode(), 'NoSuchBucket'); $this->assertEquals($e->getErrorMessage(), 'The specified bucket does not exist.'); - $this->assertEquals($e->getDetails(), $this->errorBody); + $this->assertEquals($e->getDetails(), $errorBody); } } public function testParseXml2() { - $response = new ResponseCore(array(), $this->xml, 200); + $xml = << + + + ut_test_put_bucket + ut_test_put_bucket + + + + 2015-12-17T18:12:43.000Z + oss-cn-shanghai.aliyuncs.com + oss-cn-shanghai-internal.aliyuncs.com + oss-cn-shanghai + app-base-oss + cn-shanghai + Standard + + + 2014-12-25T11:21:04.000Z + oss-cn-hangzhou.aliyuncs.com + oss-cn-hangzhou-internal.aliyuncs.com + oss-cn-hangzhou + atestleo23 + cn-hangzhou + IA + + + 2014-12-25T11:21:04.000Z + oss-cn-hangzhou + atestleo23 + + + + BBBB; + + $response = new ResponseCore(array(), $xml, 200); $result = new ListBucketsResult($response); $this->assertTrue($result->isOK()); $this->assertNotNull($result->getData()); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectVersionsResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectVersionsResultTest.php index 7fdfd7e7d..8ddbdaa1b 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectVersionsResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectVersionsResultTest.php @@ -10,106 +10,106 @@ class ListObjectVersionsResultTest extends \PHPUnit\Framework\TestCase { private $validXml = << - - oss-example - - example - CAEQMxiBgICbof2D0BYiIGRhZjgwMzJiMjA3MjQ0ODE5MWYxZDYwMzJlZjU1**** - 100 - - false - - example - CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** - false - 2019-04-09T07:27:28.000Z - - 1234512528586**** - 12345125285864390 - - - - example - CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN**** - false - 2019-04-09T07:27:28.000Z - "250F8A0AE989679A22926A875F0A2****" - Normal - 93731 - Standard - - 1234512528586**** - 12345125285864390 - - - - pic.jpg - CAEQMxiBgMCZov2D0BYiIDY4MDllOTc2YmY5MjQxMzdiOGI3OTlhNTU0ODIx**** - true - 2019-04-09T07:27:28.000Z - "3663F7B0B9D3153F884C821E7CF4****" - Normal - 574768 - IA - - 1234512528586**** - 12345125285864390 - - - -BBBB; + + + oss-example + + example + CAEQMxiBgICbof2D0BYiIGRhZjgwMzJiMjA3MjQ0ODE5MWYxZDYwMzJlZjU1**** + 100 + + false + + example + CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** + false + 2019-04-09T07:27:28.000Z + + 1234512528586**** + 12345125285864390 + + + + example + CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN**** + false + 2019-04-09T07:27:28.000Z + "250F8A0AE989679A22926A875F0A2****" + Normal + 93731 + Standard + + 1234512528586**** + 12345125285864390 + + + + pic.jpg + CAEQMxiBgMCZov2D0BYiIDY4MDllOTc2YmY5MjQxMzdiOGI3OTlhNTU0ODIx**** + true + 2019-04-09T07:27:28.000Z + "3663F7B0B9D3153F884C821E7CF4****" + Normal + 574768 + IA + + 1234512528586**** + 12345125285864390 + + + + BBBB; private $validXml1 = << - - oss-example - - example - CAEQMxiBgICbof2D0BYiIGRhZjgwMzJiMjA3MjQ0ODE5MWYxZDYwMzJlZjU1**** - 100 - - false - - example - CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** - true - 2019-04-09T07:27:28.000Z - - 1234512528586**** - 12345125285864390 - - - - example-1 - CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** - 2019-04-09T07:27:28.000Z - - 1234512528586**** - 12345125285864390 - - - - example-2 - CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN**** - 2019-04-09T07:27:28.000Z - "250F8A0AE989679A22926A875F0A2****" - Normal - 93731 - Standard - - 1234512528586**** - 12345125285864390 - - - -BBBB; + + + oss-example + + example + CAEQMxiBgICbof2D0BYiIGRhZjgwMzJiMjA3MjQ0ODE5MWYxZDYwMzJlZjU1**** + 100 + + false + + example + CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** + true + 2019-04-09T07:27:28.000Z + + 1234512528586**** + 12345125285864390 + + + + example-1 + CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm**** + 2019-04-09T07:27:28.000Z + + 1234512528586**** + 12345125285864390 + + + + example-2 + CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN**** + 2019-04-09T07:27:28.000Z + "250F8A0AE989679A22926A875F0A2****" + Normal + 93731 + Standard + + 1234512528586**** + 12345125285864390 + + + + BBBB; private $invalidXml = << - - -BBBB; + + + + BBBB; public function testParseValidXml() { @@ -136,7 +136,7 @@ BBBB; $this->assertEquals('CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****', $deleteMarkerList[0]->getVersionId()); $this->assertEquals('false', $deleteMarkerList[0]->getIsLatest()); $this->assertEquals('2019-04-09T07:27:28.000Z', $deleteMarkerList[0]->getLastModified()); - + $objectVersionList = $list->getObjectVersionList(); $this->assertEquals('example', $objectVersionList[0]->getKey()); $this->assertEquals('CAEQMxiBgMDNoP2D0BYiIDE3MWUxNzgxZDQxNTRiODI5OGYwZGMwNGY3MzZjN****', $objectVersionList[0]->getVersionId()); @@ -180,7 +180,7 @@ BBBB; $this->assertEquals('CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****', $deleteMarkerList[0]->getVersionId()); $this->assertEquals('true', $deleteMarkerList[0]->getIsLatest()); $this->assertEquals('2019-04-09T07:27:28.000Z', $deleteMarkerList[0]->getLastModified()); - + $this->assertEquals('example-1', $deleteMarkerList[1]->getKey()); $this->assertEquals('CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****', $deleteMarkerList[1]->getVersionId()); $this->assertEquals('', $deleteMarkerList[1]->getIsLatest()); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsResultTest.php index d778c2491..c977ce715 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsResultTest.php @@ -75,33 +75,6 @@ BBBB; -BBBB; - - private $validXmlWithResoreInfo = << - - testbucket-hf - url - php%2Fprefix - php%2Fmarker - php%2Fnext-marker - 1000 - %2F - true - - php/a%2Bb - 2015-11-18T03:36:00.000Z - "89B9E567E7EB8815F2F7D41851F9A2CD" - Normal - 13115 - Standard - - cname_user - cname_user - - ongoing-request="false", expiry-date="Tue, 25 Apr 2023 07:30:00 GMT" - - BBBB; public function testParseValidXml1() @@ -175,34 +148,4 @@ BBBB; $this->assertEquals(13115, $objects[0]->getSize()); $this->assertEquals('Standard', $objects[0]->getStorageClass()); } - - - public function testParseValidXmlWithRestoreInfo() - { - $response = new ResponseCore(array(), $this->validXmlWithResoreInfo, 200); - $result = new ListObjectsResult($response); - $this->assertTrue($result->isOK()); - $this->assertNotNull($result->getData()); - $this->assertNotNull($result->getRawResponse()); - $objectListInfo = $result->getData(); - $this->assertEquals(0, count($objectListInfo->getPrefixList())); - $this->assertEquals(1, count($objectListInfo->getObjectList())); - $this->assertEquals('testbucket-hf', $objectListInfo->getBucketName()); - $this->assertEquals('php/prefix', $objectListInfo->getPrefix()); - $this->assertEquals('php/marker', $objectListInfo->getMarker()); - $this->assertEquals('php/next-marker', $objectListInfo->getNextMarker()); - $this->assertEquals(1000, $objectListInfo->getMaxKeys()); - $this->assertEquals('/', $objectListInfo->getDelimiter()); - $this->assertEquals('true', $objectListInfo->getIsTruncated()); - $objects = $objectListInfo->getObjectList(); - $this->assertEquals('php/a+b', $objects[0]->getKey()); - $this->assertEquals('2015-11-18T03:36:00.000Z', $objects[0]->getLastModified()); - $this->assertEquals('"89B9E567E7EB8815F2F7D41851F9A2CD"', $objects[0]->getETag()); - $this->assertEquals('Normal', $objects[0]->getType()); - $this->assertEquals(13115, $objects[0]->getSize()); - $this->assertEquals('Standard', $objects[0]->getStorageClass()); - $this->assertEquals('ongoing-request="false", expiry-date="Tue, 25 Apr 2023 07:30:00 GMT"', $objects[0]->getRestoreInfo()); - $this->assertEquals('cname_user', $objects[0]->getOwner()->getId()); - $this->assertEquals('cname_user', $objects[0]->getOwner()->getDisplayName()); - } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsV2ResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsV2ResultTest.php index 7f07ecff6..b072cd2ed 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsV2ResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ListObjectsV2ResultTest.php @@ -74,35 +74,6 @@ BBBB; 1 -BBBB; - - private $validXmlWithRestoreInfo = << - - testbucket-hf - url - php%2Fprefix - php%2Fmarker - 1gJiYw-- - CgJiYw-- - 1000 - %2F - true - - php/a%2Bb - 2015-11-18T03:36:00.000Z - "89B9E567E7EB8815F2F7D41851F9A2CD" - Normal - 13115 - Standard - - cname_user - cname_user - - ongoing-request="false", expiry-date="Tue, 25 Apr 2023 07:30:00 GMT" - - 1 - BBBB; public function testParseValidXml1() @@ -180,36 +151,4 @@ BBBB; $this->assertEquals(13115, $objects[0]->getSize()); $this->assertEquals('Standard', $objects[0]->getStorageClass()); } - - - public function testParseValidXmlWithRestoreInfo() - { - $response = new ResponseCore(array(), $this->validXmlWithRestoreInfo, 200); - $result = new ListObjectsV2Result($response); - $this->assertTrue($result->isOK()); - $this->assertNotNull($result->getData()); - $this->assertNotNull($result->getRawResponse()); - $objectListInfo = $result->getData(); - $this->assertEquals(0, count($objectListInfo->getPrefixList())); - $this->assertEquals(1, count($objectListInfo->getObjectList())); - $this->assertEquals('testbucket-hf', $objectListInfo->getBucketName()); - $this->assertEquals('php/prefix', $objectListInfo->getPrefix()); - $this->assertEquals('php/marker', $objectListInfo->getStartAfter()); - $this->assertEquals('CgJiYw--', $objectListInfo->getNextContinuationToken()); - $this->assertEquals('1gJiYw--', $objectListInfo->getContinuationToken()); - $this->assertEquals(1000, $objectListInfo->getMaxKeys()); - $this->assertEquals('/', $objectListInfo->getDelimiter()); - $this->assertEquals('true', $objectListInfo->getIsTruncated()); - $this->assertEquals(1, $objectListInfo->getKeyCount()); - $objects = $objectListInfo->getObjectList(); - $this->assertEquals('php/a+b', $objects[0]->getKey()); - $this->assertEquals('2015-11-18T03:36:00.000Z', $objects[0]->getLastModified()); - $this->assertEquals('"89B9E567E7EB8815F2F7D41851F9A2CD"', $objects[0]->getETag()); - $this->assertEquals('Normal', $objects[0]->getType()); - $this->assertEquals(13115, $objects[0]->getSize()); - $this->assertEquals('Standard', $objects[0]->getStorageClass()); - $this->assertEquals('ongoing-request="false", expiry-date="Tue, 25 Apr 2023 07:30:00 GMT"', $objects[0]->getRestoreInfo()); - $this->assertEquals('cname_user', $objects[0]->getOwner()->getId()); - $this->assertEquals('cname_user', $objects[0]->getOwner()->getDisplayName()); - } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ObjectAclTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ObjectAclTest.php index ec003ca72..9260a6a5d 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ObjectAclTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/ObjectAclTest.php @@ -3,7 +3,6 @@ namespace OSS\Tests; require_once __DIR__ . '/Common.php'; -require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestOssClientBase.php'; class ObjectAclTest extends TestOssClientBase { diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketCorsTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketCorsTest.php index bbe11f512..a32154b55 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketCorsTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketCorsTest.php @@ -7,7 +7,6 @@ use OSS\Model\CorsConfig; use OSS\Model\CorsRule; use OSS\OssClient; - require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestOssClientBase.php'; @@ -39,7 +38,6 @@ class OssClientBucketCorsTest extends TestOssClientBase $rule->addExposeHeader("x-oss-test1"); $rule->setMaxAgeSeconds(110); $corsConfig->addRule($rule); - $corsConfig->setResponseVary(true); try { $this->ossClient->putBucketCors($this->bucket, $corsConfig); @@ -82,44 +80,5 @@ class OssClientBucketCorsTest extends TestOssClientBase $this->assertFalse(True); } - - try { - Common::waitMetaSync(); - $this->ossClient->deleteBucketCors($this->bucket); - } catch (OssException $e) { - $this->assertFalse(True); - } - - $corsConfig = new CorsConfig(); - $rule = new CorsRule(); - $rule->addAllowedHeader("x-oss-test"); - $rule->addAllowedOrigin("http://www.b.com"); - $rule->addAllowedMethod("GET"); - $rule->addExposeHeader("x-oss-test1"); - $rule->setMaxAgeSeconds(10); - $corsConfig->addRule($rule); - $rule = new CorsRule(); - $rule->addAllowedHeader("x-oss-test"); - $rule->addAllowedMethod("GET"); - $rule->addAllowedOrigin("http://www.b.com"); - $rule->addExposeHeader("x-oss-test1"); - $rule->setMaxAgeSeconds(110); - $corsConfig->addRule($rule); - $corsConfig->setResponseVary(false); - - try { - $this->ossClient->putBucketCors($this->bucket, $corsConfig); - } catch (OssException $e) { - $this->assertFalse(True); - } - - try { - Common::waitMetaSync(); - $corsConfig4 = $this->ossClient->getBucketCors($this->bucket); - $this->assertNotNull($corsConfig4); - $this->assertEquals($corsConfig->serializeToXml(), $corsConfig4->serializeToXml()); - } catch (OssException $e) { - $this->assertFalse(True); - } } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketPolicyTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketPolicyTest.php index 6007f1071..4f0c5ee66 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketPolicyTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketPolicyTest.php @@ -1,5 +1,4 @@ ossClient->deleteBucketPolicy($this->bucket); @@ -43,9 +38,7 @@ BBBB; try { $this->ossClient->putBucketPolicy($this->bucket, $policy_str); $policy = $this->ossClient->getBucketPolicy($this->bucket); - $data1 = json_decode($policy_str, true); - $data2 = json_decode($policy, true); - $this->assertEquals($data1, $data2); + $this->assertEquals($policy_str, $policy); $this->ossClient->deleteBucketPolicy($this->bucket); } catch (OssException $e) { $this->assertTrue(false); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketTest.php index dc6368551..6bac445e3 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientBucketTest.php @@ -52,11 +52,11 @@ class OssClientBucketTest extends TestOssClientBase $this->assertTrue($this->ossClient->doesBucketExist($this->bucket)); $this->assertFalse($this->ossClient->doesBucketExist($this->bucket . '-notexist')); - //$this->assertContains(Common::getRegion(), $this->ossClient->getBucketLocation($this->bucket)); + $this->assertEquals($this->ossClient->getBucketLocation($this->bucket), Common::getRegion()); $res = $this->ossClient->getBucketMeta($this->bucket); $this->assertEquals('200', $res['info']['http_code']); - //$this->assertContains(Common::getRegion(), $res['x-oss-bucket-region']); + $this->assertEquals(Common::getRegion(), $res['x-oss-bucket-region']); } public function testCreateBucketWithStorageType() diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientImageTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientImageTest.php index a43584eb0..6def9f971 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientImageTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientImageTest.php @@ -4,11 +4,9 @@ namespace OSS\Tests; require_once __DIR__ . '/Common.php'; -require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestOssClientBase.php'; - use OSS\OssClient; -class OssClientImageTest extends TestOssClientBase +class OssClinetImageTest extends TestOssClientBase { private $bucketName; private $client; @@ -35,20 +33,20 @@ class OssClientImageTest extends TestOssClientBase parent::tearDown(); unlink($this->download_file); } - + public function testImageResize() { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/resize,m_fixed,h_100,w_100",); + OssClient::OSS_PROCESS => "image/resize,m_fixed,h_100,w_100", ); $this->check($options, 100, 100, 3267, 'jpg'); } - + public function testImageCrop() { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/crop,w_100,h_100,x_100,y_100,r_1",); + OssClient::OSS_PROCESS => "image/crop,w_100,h_100,x_100,y_100,r_1", ); $this->check($options, 100, 100, 1969, 'jpg'); } @@ -56,7 +54,7 @@ class OssClientImageTest extends TestOssClientBase { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/rotate,90",); + OssClient::OSS_PROCESS => "image/rotate,90", ); $this->check($options, 267, 400, 20998, 'jpg'); } @@ -64,7 +62,7 @@ class OssClientImageTest extends TestOssClientBase { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/sharpen,100",); + OssClient::OSS_PROCESS => "image/sharpen,100", ); $this->check($options, 400, 267, 23015, 'jpg'); } @@ -72,7 +70,7 @@ class OssClientImageTest extends TestOssClientBase { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ",); + OssClient::OSS_PROCESS => "image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ", ); $this->check($options, 400, 267, 26369, 'jpg'); } @@ -80,7 +78,7 @@ class OssClientImageTest extends TestOssClientBase { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/format,png",); + OssClient::OSS_PROCESS => "image/format,png", ); $this->check($options, 400, 267, 160733, 'png'); } @@ -88,22 +86,22 @@ class OssClientImageTest extends TestOssClientBase { $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, - OssClient::OSS_PROCESS => "image/resize,m_fixed,w_100,h_100",); + OssClient::OSS_PROCESS => "image/resize,m_fixed,w_100,h_100", ); $this->check($options, 100, 100, 3267, 'jpg'); } public function testProcesObject() { $object = 'process-object.jpg'; - $process = 'image/resize,m_fixed,w_100,h_100' . - '|sys/saveas' . - ',o_' . $this->base64url_encode($object) . - ',b_' . $this->base64url_encode($this->bucketName); + $process = 'image/resize,m_fixed,w_100,h_100'. + '|sys/saveas'. + ',o_'.$this->base64url_encode($object). + ',b_'.$this->base64url_encode($this->bucketName); $result = $this->client->processObject($this->bucketName, $this->object, $process); $this->assertTrue(stripos($result, '"object": "process-object.jpg",') > 0); $this->assertTrue(stripos($result, '"status": "OK"') > 0); - + $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, ); @@ -115,14 +113,14 @@ class OssClientImageTest extends TestOssClientBase //without bucket $object = 'process-object-1.jpg'; - $process = 'image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ' . - '|sys/saveas' . - ',o_' . $this->base64url_encode($object); + $process = 'image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ'. + '|sys/saveas'. + ',o_'.$this->base64url_encode($object); $result = $this->client->processObject($this->bucketName, $this->object, $process); $this->assertTrue(stripos($result, '"object": "process-object-1.jpg",') > 0); $this->assertTrue(stripos($result, '"status": "OK"') > 0); - + $options = array( OssClient::OSS_FILE_DOWNLOAD => $this->download_file, ); @@ -144,6 +142,6 @@ class OssClientImageTest extends TestOssClientBase private function base64url_encode($data) { - return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); + return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientMultipartUploadTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientMultipartUploadTest.php index 3cd6a1e47..5a6c45847 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientMultipartUploadTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientMultipartUploadTest.php @@ -399,6 +399,7 @@ class OssClientMultipartUploadTest extends TestOssClientBase try { $uploadId = $this->ossClient->initiateMultipartUpload($this->bucket, $object); $listMultipartUploadInfo = $this->ossClient->completeMultipartUpload($this->bucket, $object, $uploadId, array()); + var_dump($listMultipartUploadInfo); $this->assertNotNull($listMultipartUploadInfo); } catch (OssException $e) { $this->assertFalse(true); @@ -464,6 +465,7 @@ class OssClientMultipartUploadTest extends TestOssClientBase try { $result = $this->ossClient->completeMultipartUpload($this->bucket, $object, $upload_id, null,$options); + var_dump($result); $this->assertNotNull($result); } catch (OssException $e) { $this->assertTrue(false); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectRequestPaymentTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectRequestPaymentTest.php index 9f645d31b..66251880d 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectRequestPaymentTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectRequestPaymentTest.php @@ -451,12 +451,12 @@ class OssClientObjectRequestPaymentTest extends TestOssClientBase { parent::setUp(); $this->payerClient = new OssClient( - Common::getPayerAccessKeyId(), - Common::getPayerAccessKeySecret(), - Common::getEndpoint(), false); + getenv('OSS_PAYER_ACCESS_KEY_ID'), + getenv('OSS_PAYER_ACCESS_KEY_SECRET'), + getenv('OSS_ENDPOINT'), false); $policy = '{"Version":"1","Statement":[{"Action":["oss:*"],"Effect": "Allow",'. - '"Principal":["' . Common::getPayerUid() . '"],'. + '"Principal":["' . getenv('OSS_PAYER_UID') . '"],'. '"Resource": ["acs:oss:*:*:' . $this->bucket . '","acs:oss:*:*:' . $this->bucket . '/*"]}]}'; $this->ossClient->putBucketPolicy($this->bucket, $policy); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectTest.php index a573f1587..bb6101889 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientObjectTest.php @@ -3,7 +3,6 @@ namespace OSS\Tests; use OSS\Core\OssException; -use OSS\Core\OssUtil; use OSS\OssClient; require_once __DIR__ . DIRECTORY_SEPARATOR . 'TestOssClientBase.php'; @@ -21,7 +20,8 @@ class OssClientObjectTest extends TestOssClientBase $this->assertEquals('200', $res['info']['http_code']); $this->assertEquals('text/plain', $res['content-type']); $this->assertEquals('Accept-Encoding', $res['vary']); - $this->assertTrue(isset($res['content-encoding'])); + $this->assertTrue(isset($res['content-length'])); + $this->assertFalse(isset($res['content-encoding'])); } catch (OssException $e) { $this->assertTrue(false); } @@ -33,6 +33,7 @@ class OssClientObjectTest extends TestOssClientBase $this->assertEquals('200', $res['info']['http_code']); $this->assertEquals('text/plain', $res['content-type']); $this->assertEquals('Accept-Encoding', $res['vary']); + $this->assertFalse(isset($res['content-length'])); $this->assertEquals('gzip', $res['content-encoding']); } catch (OssException $e) { $this->assertTrue(false); @@ -98,13 +99,13 @@ class OssClientObjectTest extends TestOssClientBase } catch (OssException $e) { $this->assertFalse(true); } - + try { - $this->ossClient->putObject($this->bucket, $object, $content, $options); + $this->ossClient->putObject($this->bucket, $object, $content, $options); } catch (OssException $e) { - $this->assertFalse(true); + $this->assertFalse(true); } - + try { $result = $this->ossClient->deleteObjects($this->bucket, "stringtype", $options); $this->assertEquals('stringtype', $result[0]); @@ -199,7 +200,8 @@ class OssClientObjectTest extends TestOssClientBase } catch (OssException $e) { $this->assertTrue(true); $this->assertFalse(file_exists($localfile)); - if (strpos($e, "The specified key does not exist") == false) { + if (strpos($e, "The specified key does not exist") == false) + { $this->assertTrue(true); } } @@ -212,7 +214,8 @@ class OssClientObjectTest extends TestOssClientBase $this->assertTrue(false); } catch (OssException $e) { $this->assertTrue(true); - if (strpos($e, "The specified key does not exist") == false) { + if (strpos($e, "The specified key does not exist") == false) + { $this->assertTrue(true); } } @@ -232,7 +235,7 @@ class OssClientObjectTest extends TestOssClientBase $this->assertFalse(true); var_dump($e->getMessage()); - } + } /** * Check if the replication is the same @@ -322,11 +325,11 @@ class OssClientObjectTest extends TestOssClientBase $list = array($object1, $object2); try { $this->assertTrue($this->ossClient->doesObjectExist($this->bucket, $object2)); - + $result = $this->ossClient->deleteObjects($this->bucket, $list); $this->assertEquals($list[0], $result[0]); $this->assertEquals($list[1], $result[1]); - + $result = $this->ossClient->deleteObjects($this->bucket, $list, array('quiet' => 'true')); $this->assertEquals(array(), $result); $this->assertFalse($this->ossClient->doesObjectExist($this->bucket, $object2)); @@ -345,7 +348,7 @@ class OssClientObjectTest extends TestOssClientBase { $object = "oss-php-sdk-test/append-test-object-name.txt"; $content_array = array('Hello OSS', 'Hi OSS', 'OSS OK'); - + /** * Append the upload string */ @@ -370,7 +373,7 @@ class OssClientObjectTest extends TestOssClientBase $this->assertFalse(true); } - + /** * Delete test object */ @@ -379,7 +382,7 @@ class OssClientObjectTest extends TestOssClientBase } catch (OssException $e) { $this->assertFalse(true); } - + /** * Append the upload of invalid local files */ @@ -395,9 +398,9 @@ class OssClientObjectTest extends TestOssClientBase */ try { $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, 0); - $this->assertEquals($position, sprintf('%u', filesize(__FILE__))); + $this->assertEquals($position, sprintf('%u',filesize(__FILE__))); $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, $position); - $this->assertEquals($position, sprintf('%u', filesize(__FILE__)) * 2); + $this->assertEquals($position, sprintf('%u',filesize(__FILE__)) * 2); } catch (OssException $e) { $this->assertFalse(true); } @@ -411,7 +414,7 @@ class OssClientObjectTest extends TestOssClientBase } catch (OssException $e) { $this->assertFalse(true); } - + /** * Delete test object */ @@ -458,138 +461,138 @@ class OssClientObjectTest extends TestOssClientBase $this->assertFalse(true); } } - + public function testPutIllelObject() { - $object = "/ilegal.txt"; - try { - $this->ossClient->putObject($this->bucket, $object, "hi", null); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('"/ilegal.txt" object name is invalid', $e->getMessage()); - } + $object = "/ilegal.txt"; + try { + $this->ossClient->putObject($this->bucket, $object, "hi", null); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals('"/ilegal.txt" object name is invalid', $e->getMessage()); + } } - + public function testCheckMD5() { - $object = "oss-php-sdk-test/upload-test-object-name.txt"; - $content = file_get_contents(__FILE__); - $options = array(OssClient::OSS_CHECK_MD5 => true); + $object = "oss-php-sdk-test/upload-test-object-name.txt"; + $content = file_get_contents(__FILE__); + $options = array(OssClient::OSS_CHECK_MD5 => true); + + /** + * Upload data to start MD5 + */ + try { + $this->ossClient->putObject($this->bucket, $object, $content, $options); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Check if the replication is the same + */ + try { + $content = $this->ossClient->getObject($this->bucket, $object); + $this->assertEquals($content, file_get_contents(__FILE__)); + } catch (OssException $e) { + $this->assertFalse(true); + } - /** - * Upload data to start MD5 - */ - try { - $this->ossClient->putObject($this->bucket, $object, $content, $options); - } catch (OssException $e) { - $this->assertFalse(true); - } + /** + * Upload file to start MD5 + */ + try { + $this->ossClient->uploadFile($this->bucket, $object, __FILE__, $options); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Check if the replication is the same + */ + try { + $content = $this->ossClient->getObject($this->bucket, $object); + $this->assertEquals($content, file_get_contents(__FILE__)); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Delete test object + */ + try { + $this->ossClient->deleteObject($this->bucket, $object); + } catch (OssException $e) { + $this->assertFalse(true); + } - /** - * Check if the replication is the same - */ - try { - $content = $this->ossClient->getObject($this->bucket, $object); - $this->assertEquals($content, file_get_contents(__FILE__)); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Upload file to start MD5 - */ - try { - $this->ossClient->uploadFile($this->bucket, $object, __FILE__, $options); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Check if the replication is the same - */ - try { - $content = $this->ossClient->getObject($this->bucket, $object); - $this->assertEquals($content, file_get_contents(__FILE__)); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Delete test object - */ - try { - $this->ossClient->deleteObject($this->bucket, $object); - } catch (OssException $e) { - $this->assertFalse(true); - } - - $object = "oss-php-sdk-test/append-test-object-name.txt"; - $content_array = array('Hello OSS', 'Hi OSS', 'OSS OK'); - $options = array(OssClient::OSS_CHECK_MD5 => true); - - /** - * Append the upload string - */ - try { - $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[0], 0, $options); - $this->assertEquals($position, strlen($content_array[0])); - $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[1], $position, $options); - $this->assertEquals($position, strlen($content_array[0]) + strlen($content_array[1])); - $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[2], $position, $options); - $this->assertEquals($position, strlen($content_array[0]) + strlen($content_array[1]) + strlen($content_array[1])); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Check if the content is the same - */ - try { - $content = $this->ossClient->getObject($this->bucket, $object); - $this->assertEquals($content, implode($content_array)); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Delete test object - */ - try { - $this->ossClient->deleteObject($this->bucket, $object); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Append upload of local files - */ - try { - $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, 0, $options); - $this->assertEquals($position, sprintf('%u', filesize(__FILE__))); - $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, $position, $options); - $this->assertEquals($position, sprintf('%u', filesize(__FILE__)) * 2); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * Check if the replication is the same - */ - try { - $content = $this->ossClient->getObject($this->bucket, $object); - $this->assertEquals($content, file_get_contents(__FILE__) . file_get_contents(__FILE__)); - } catch (OssException $e) { - $this->assertFalse(true); - } - - /** - * delete test object - */ - try { - $this->ossClient->deleteObject($this->bucket, $object); - } catch (OssException $e) { - $this->assertFalse(true); - } + $object = "oss-php-sdk-test/append-test-object-name.txt"; + $content_array = array('Hello OSS', 'Hi OSS', 'OSS OK'); + $options = array(OssClient::OSS_CHECK_MD5 => true); + + /** + * Append the upload string + */ + try { + $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[0], 0, $options); + $this->assertEquals($position, strlen($content_array[0])); + $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[1], $position, $options); + $this->assertEquals($position, strlen($content_array[0]) + strlen($content_array[1])); + $position = $this->ossClient->appendObject($this->bucket, $object, $content_array[2], $position, $options); + $this->assertEquals($position, strlen($content_array[0]) + strlen($content_array[1]) + strlen($content_array[1])); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Check if the content is the same + */ + try { + $content = $this->ossClient->getObject($this->bucket, $object); + $this->assertEquals($content, implode($content_array)); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Delete test object + */ + try { + $this->ossClient->deleteObject($this->bucket, $object); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Append upload of local files + */ + try { + $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, 0, $options); + $this->assertEquals($position, sprintf('%u',filesize(__FILE__))); + $position = $this->ossClient->appendFile($this->bucket, $object, __FILE__, $position, $options); + $this->assertEquals($position, sprintf('%u',filesize(__FILE__)) * 2); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * Check if the replication is the same + */ + try { + $content = $this->ossClient->getObject($this->bucket, $object); + $this->assertEquals($content, file_get_contents(__FILE__) . file_get_contents(__FILE__)); + } catch (OssException $e) { + $this->assertFalse(true); + } + + /** + * delete test object + */ + try { + $this->ossClient->deleteObject($this->bucket, $object); + } catch (OssException $e) { + $this->assertFalse(true); + } } public function testWithInvalidBucketName() @@ -623,8 +626,8 @@ class OssClientObjectTest extends TestOssClientBase $options = array(OssClient::OSS_CHECK_MD5 => true); $handle = fopen(__FILE__, 'rb'); /** - * Upload data to start MD5 - */ + * Upload data to start MD5 + */ try { $this->ossClient->uploadStream($this->bucket, $object, $handle, $options); } catch (OssException $e) { @@ -632,8 +635,8 @@ class OssClientObjectTest extends TestOssClientBase } /** - * Check if the replication is the same - */ + * Check if the replication is the same + */ try { $content = $this->ossClient->getObject($this->bucket, $object); $this->assertEquals($content, file_get_contents(__FILE__)); @@ -650,8 +653,8 @@ class OssClientObjectTest extends TestOssClientBase } /** - * Check if the replication is the same - */ + * Check if the replication is the same + */ try { $content = $this->ossClient->getObject($this->bucket, $object); $this->assertEquals($content, file_get_contents(__FILE__)); @@ -748,7 +751,7 @@ class OssClientObjectTest extends TestOssClientBase $this->assertFalse(true); var_dump($e->getMessage()); - } + } /** * Check if the replication is the same @@ -770,166 +773,6 @@ class OssClientObjectTest extends TestOssClientBase } } - public function testObjectKeyWithNonUTF8Name() - { - $object = "中文测试.txt"; - $hexObject = bin2hex($object); - $gbkObject = iconv('UTF-8', 'GBK', $object); - $hexGbkObject = bin2hex($gbkObject); - $content = "hello world"; - - $this->assertEquals("e4b8ade69687e6b58be8af952e747874", $hexObject); - $this->assertEquals("d6d0cec4b2e2cad42e747874", $hexGbkObject); - - try { - $this->ossClient->putObject($this->bucket, $gbkObject, $content); - $this->assertTrue(false); - } catch (OssException $e) { - $this->assertEquals('InvalidArgument', $e->getErrorCode()); - $this->assertEquals('The characters encoding must be utf-8.', $e->getErrorMessage()); - } catch (\Exception $e) { - $this->assertTrue(false); - } - - //enable object encoding check - $config = array( - 'checkObjectEncoding' => true, - ); - $ossClient = Common::getOssClient($config); - try { - $ossClient->putObject($this->bucket, $gbkObject, $content); - $content1 = $this->ossClient->getObject($this->bucket, $object); - $content2 = $ossClient->getObject($this->bucket, $gbkObject); - $this->assertEquals($content, $content1); - $this->assertEquals($content, $content2); - } catch (\Exception $e) { - $this->assertTrue(false); - } - - // ascii - try { - $ossClient->putObject($this->bucket, '1234', 'ascii'); - $content1 = $this->ossClient->getObject($this->bucket, '1234'); - $content2 = $ossClient->getObject($this->bucket, '1234'); - $this->assertEquals('ascii', $content1); - $this->assertEquals('ascii', $content2); - } catch (\Exception $e) { - $this->assertTrue(false); - } - } - - public function testEncodeFilePath() - { - if (!OssUtil::isWin()) { - $this->assertTrue(true); - return; - } - - $fileFolder = __DIR__ . DIRECTORY_SEPARATOR . "中文目录"; - $filePath1 = $fileFolder . DIRECTORY_SEPARATOR . "中文文件名1.txt"; - $filePath2 = $fileFolder . DIRECTORY_SEPARATOR . "中文文件名2.txt"; - - $gbkfileFolder = iconv('UTF-8', 'GBK', $fileFolder); - $gbkfilePath1 = iconv('UTF-8', 'GBK', $filePath1); - $gbkfilePath2 = iconv('UTF-8', 'GBK', $filePath2); - - $hexfilePath1 = bin2hex($filePath1); - $hexGbkfilePath2 = bin2hex($gbkfilePath2); - - $content1 = ''; - $content2 = ''; - if (version_compare(phpversion(), '7.0.0', '<')) { - try { - mkdir($gbkfileFolder); - } catch (\Exception $e) { - } - OssUtil::generateFile($gbkfilePath1, 200 * 1024); - OssUtil::generateFile($gbkfilePath2, 202 * 1024); - $content1 = file_get_contents($gbkfilePath1); - $content2 = file_get_contents($gbkfilePath2); - } else { - try { - mkdir($fileFolder); - } catch (\Exception $e) { - } - OssUtil::generateFile($filePath1, 200 * 1024); - OssUtil::generateFile($filePath2, 202 * 1024); - $content1 = file_get_contents($filePath1); - $content2 = file_get_contents($filePath2); - } - - try { - - // upload file - $this->ossClient->uploadFile($this->bucket, '123', $filePath1); - $this->ossClient->uploadFile($this->bucket, '234', $gbkfilePath2); - - $res = $this->ossClient->getObject($this->bucket, '123'); - $this->assertEquals($content1, $res); - - $res = $this->ossClient->getObject($this->bucket, '234'); - $this->assertEquals($content2, $res); - - // append file - $position = $this->ossClient->appendFile($this->bucket, 'append-file', $filePath1, 0); - $position = $this->ossClient->appendFile($this->bucket, 'append-file', $gbkfilePath2, $position); - - $res = $this->ossClient->getObject($this->bucket, 'append-file'); - $this->assertEquals($content1.$content2, $res); - - // multi paet - $this->ossClient->multiuploadFile($this->bucket, 'multi-file-123', $filePath1, array(OssClient::OSS_PART_SIZE => 1)); - $this->ossClient->multiuploadFile($this->bucket, 'multi-file-234', $gbkfilePath2, array(OssClient::OSS_PART_SIZE => 1)); - $res = $this->ossClient->getObject($this->bucket, 'multi-file-123'); - $this->assertEquals($content1, $res); - - $res = $this->ossClient->getObject($this->bucket, 'multi-file-234'); - $this->assertEquals($content2, $res); - - // uploadDir - $this->ossClient->uploadDir($this->bucket, "dir", $fileFolder); - $options = array( - 'delimiter' => '', - 'prefix' => "dir", - ); - $listObjectInfo = $this->ossClient->listObjects($this->bucket, $options); - $objectList = $listObjectInfo->getObjectList(); - $this->assertEquals(2, count($objectList)); - $this->assertEquals('dir/中文文件名1.txt', $objectList[0]->getKey()); - $this->assertEquals('dir/中文文件名2.txt', $objectList[1]->getKey()); - - // uploadDir - if (version_compare(phpversion(), '7.0.0', '<')) { - $this->ossClient->uploadDir($this->bucket, "gbkdir", $gbkfileFolder); - $options = array( - 'delimiter' => '', - 'prefix' => "gbkdir", - ); - $listObjectInfo = $this->ossClient->listObjects($this->bucket, $options); - $objectList = $listObjectInfo->getObjectList(); - $this->assertEquals(2, count($objectList)); - $this->assertEquals('gbkdir/中文文件名1.txt', $objectList[0]->getKey()); - $this->assertEquals('gbkdir/中文文件名2.txt', $objectList[1]->getKey()); - } - - } catch (OssException $e) { - $this->assertFalse(true); - } - - try { - if (phpversion() < "7.0.0") { - unlink($gbkfilePath1); - unlink($gbkfilePath2); - rmdir($gbkfileFolder); - } else { - unlink($filePath1); - unlink($filePath2); - rmdir($fileFolder); - } - } catch (\Exception $e) { - } - } - protected function setUp(): void { parent::setUp(); diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientSignatureTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientSignatureTest.php index 7187a665f..00cf89a5e 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientSignatureTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientSignatureTest.php @@ -1,267 +1,167 @@ -ossClient->putObject($this->bucket, $object, file_get_contents(__FILE__)); - $timeout = 3600; - try { - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout); - } catch (OssException $e) { - $this->assertFalse(true); - } - - $request = new RequestCore($signedUrl); - $request->set_method('GET'); - $request->add_header('Content-Type', ''); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code()); - $this->assertEquals(file_get_contents(__FILE__), $res->body); - } - - public function testGetSignedUrlForPuttingObject() - { - $object = "a.file"; - $timeout = 3600; - try { - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT"); - $content = file_get_contents(__FILE__); - $request = new RequestCore($signedUrl); - $request->set_method('PUT'); - $request->add_header('Content-Type', ''); - $request->add_header('Content-Length', strlen($content)); - $request->set_body($content); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), - $request->get_response_body(), $request->get_response_code()); - $this->assertTrue($res->isOK()); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testGetSignedUrlForPuttingObjectFromFile() - { - $file = __FILE__; - $object = "a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - try { - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $request = new RequestCore($signedUrl); - $request->set_method('PUT'); - $request->add_header('Content-Type', 'txt'); - $request->set_read_file($file); - $request->set_read_stream_size(sprintf('%u',filesize($file))); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), - $request->get_response_body(), $request->get_response_code()); - $this->assertTrue($res->isOK()); - } catch (OssException $e) { - $this->assertFalse(true); - } - - } - - public function testSignedUrlWithException() - { - $file = __FILE__; - $object = "a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - try { - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "POST", $options); - $this->assertTrue(false); - } catch (OssException $e) { - $this->assertTrue(true); - if (strpos($e, "method is invalid") == false) - { - $this->assertTrue(false); - } - } - - $object = "?a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - try { - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(false); - } catch (OssException $e) { - $this->assertTrue(true); - if (strpos($e, "object name cannot start with `?`") == false) - { - $this->assertTrue(false); - } - } - - // Set StrictObjectName false - $object = "?a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - $config = array( - 'strictObjectName' => false - ); - $ossClient = Common::getOssClient($config); - try { - $signedUrl = $ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(true); - } catch (OssException $e) { - print_r($e->getMessage()); - $this->assertFalse(true); - } - - // V4 - $object = "?a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - $config = array( - 'signatureVersion' => OssClient::OSS_SIGNATURE_VERSION_V4 - ); - $ossClient = Common::getOssClient($config); - try { - $signedUrl = $ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(true); - } catch (OssException $e) { - print_r($e->getMessage()); - $this->assertFalse(true); - } - } - - function testGetgenPreSignedUrlForGettingObject() - { - $object = "a.file"; - $this->ossClient->putObject($this->bucket, $object, file_get_contents(__FILE__)); - $expires = time() + 3600; - try { - $signedUrl = $this->ossClient->generatePresignedUrl($this->bucket, $object, $expires); - } catch (OssException $e) { - $this->assertFalse(true); - } - - $request = new RequestCore($signedUrl); - $request->set_method('GET'); - $request->add_header('Content-Type', ''); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code()); - $this->assertEquals(file_get_contents(__FILE__), $res->body); - } - - function testGetgenPreSignedUrlVsSignedUrl() - { - $object = "object-vs.file"; - $signedUrl1 = '245'; - $signedUrl2 = '123'; - $expiration = 0; - - do { - usleep(500000); - $begin = time(); - $expiration = time() + 3600; - $signedUrl1 = $this->ossClient->generatePresignedUrl($this->bucket, $object, $expiration); - $signedUrl2 = $this->ossClient->signUrl($this->bucket, $object, 3600); - $end = time(); - } while ($begin != $end); - $this->assertEquals($signedUrl1, $signedUrl2); - $this->assertTrue(strpos($signedUrl1, 'Expires='.$expiration) !== false); - } - - public function testPutObjectWithQueryCallback() - { - $object = "a.file"; - $timeout = 3600; - $url = '{"callbackUrl":"http://aliyun.com", "callbackBody":"bucket=${bucket}&object=${object}"}'; - $var = - '{ - "x:var1":"value1", - "x:var2":"value2" - }'; - try { - $options[OssClient::OSS_QUERY_STRING] = array( - 'callback'=>base64_encode($url), - 'callback-var'=>base64_encode($var) - ); - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $content = file_get_contents(__FILE__); - $request = new RequestCore($signedUrl); - $request->set_method('PUT'); - $request->add_header('Content-Type', ''); - $request->add_header('Content-Length', strlen($content)); - $request->set_body($content); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), - $request->get_response_body(), $request->get_response_code()); - $this->assertEquals($res->status, 203); - } catch (OssException $e) { - $this->assertFalse(true); - } - - try { - $options = array(OssClient::OSS_CALLBACK => $url, - OssClient::OSS_CALLBACK_VAR => $var - ); - $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); - $content = file_get_contents(__FILE__); - $request = new RequestCore($signedUrl); - $request->set_method('PUT'); - $request->add_header('Content-Type', ''); - $request->add_header(OssClient::OSS_CALLBACK, base64_encode($url)); - $request->add_header(OssClient::OSS_CALLBACK_VAR , base64_encode($var)); - $request->add_header('Content-Length', strlen($content)); - $request->set_body($content); - $request->send_request(); - $res = new ResponseCore($request->get_response_header(), - $request->get_response_body(), $request->get_response_code()); - $this->assertEquals($res->status, 203); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - - protected function tearDown(): void - { - $this->ossClient->deleteObject($this->bucket, "a.file"); - parent::tearDown(); - } - - protected function setUp(): void - { - parent::setUp(); - /** - * 上传本地变量到bucket - */ - $object = "a.file"; - $content = file_get_contents(__FILE__); - $options = array( - OssClient::OSS_LENGTH => strlen($content), - OssClient::OSS_HEADERS => array( - 'Expires' => 'Fri, 28 Feb 2020 05:38:42 GMT', - 'Cache-Control' => 'no-cache', - 'Content-Disposition' => 'attachment;filename=oss_download.log', - 'Content-Encoding' => 'utf-8', - 'Content-Language' => 'zh-CN', - 'x-oss-server-side-encryption' => 'AES256', - 'x-oss-meta-self-define-title' => 'user define meta info', - ), - ); - - try { - $this->ossClient->putObject($this->bucket, $object, $content, $options); - } catch (OssException $e) { - $this->assertFalse(true); - } - } -} +ossClient->putObject($this->bucket, $object, file_get_contents(__FILE__)); + $timeout = 3600; + try { + $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout); + } catch (OssException $e) { + $this->assertFalse(true); + } + + $request = new RequestCore($signedUrl); + $request->set_method('GET'); + $request->add_header('Content-Type', ''); + $request->send_request(); + $res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code()); + $this->assertEquals(file_get_contents(__FILE__), $res->body); + } + + public function testGetSignedUrlForPuttingObject() + { + $object = "a.file"; + $timeout = 3600; + try { + $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT"); + $content = file_get_contents(__FILE__); + $request = new RequestCore($signedUrl); + $request->set_method('PUT'); + $request->add_header('Content-Type', ''); + $request->add_header('Content-Length', strlen($content)); + $request->set_body($content); + $request->send_request(); + $res = new ResponseCore($request->get_response_header(), + $request->get_response_body(), $request->get_response_code()); + $this->assertTrue($res->isOK()); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testGetSignedUrlForPuttingObjectFromFile() + { + $file = __FILE__; + $object = "a.file"; + $timeout = 3600; + $options = array('Content-Type' => 'txt'); + try { + $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "PUT", $options); + $request = new RequestCore($signedUrl); + $request->set_method('PUT'); + $request->add_header('Content-Type', 'txt'); + $request->set_read_file($file); + $request->set_read_stream_size(sprintf('%u',filesize($file))); + $request->send_request(); + $res = new ResponseCore($request->get_response_header(), + $request->get_response_body(), $request->get_response_code()); + $this->assertTrue($res->isOK()); + } catch (OssException $e) { + $this->assertFalse(true); + } + + } + + public function testSignedUrlWithException() + { + $file = __FILE__; + $object = "a.file"; + $timeout = 3600; + $options = array('Content-Type' => 'txt'); + try { + $signedUrl = $this->ossClient->signUrl($this->bucket, $object, $timeout, "POST", $options); + $this->assertTrue(false); + } catch (OssException $e) { + $this->assertTrue(true); + if (strpos($e, "method is invalid") == false) + { + $this->assertTrue(false); + } + } + } + + function testGetgenPreSignedUrlForGettingObject() + { + $object = "a.file"; + $this->ossClient->putObject($this->bucket, $object, file_get_contents(__FILE__)); + $expires = time() + 3600; + try { + $signedUrl = $this->ossClient->generatePresignedUrl($this->bucket, $object, $expires); + } catch (OssException $e) { + $this->assertFalse(true); + } + + $request = new RequestCore($signedUrl); + $request->set_method('GET'); + $request->add_header('Content-Type', ''); + $request->send_request(); + $res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code()); + $this->assertEquals(file_get_contents(__FILE__), $res->body); + } + + function testGetgenPreSignedUrlVsSignedUrl() + { + $object = "object-vs.file"; + $signedUrl1 = '245'; + $signedUrl2 = '123'; + $expiration = 0; + + do { + usleep(500000); + $begin = time(); + $expiration = time() + 3600; + $signedUrl1 = $this->ossClient->generatePresignedUrl($this->bucket, $object, $expiration); + $signedUrl2 = $this->ossClient->signUrl($this->bucket, $object, 3600); + $end = time(); + } while ($begin != $end); + $this->assertEquals($signedUrl1, $signedUrl2); + $this->assertTrue(strpos($signedUrl1, 'Expires='.$expiration) !== false); + } + + protected function tearDown(): void + { + $this->ossClient->deleteObject($this->bucket, "a.file"); + parent::tearDown(); + } + + protected function setUp(): void + { + parent::setUp(); + /** + * 上传本地变量到bucket + */ + $object = "a.file"; + $content = file_get_contents(__FILE__); + $options = array( + OssClient::OSS_LENGTH => strlen($content), + OssClient::OSS_HEADERS => array( + 'Expires' => 'Fri, 28 Feb 2020 05:38:42 GMT', + 'Cache-Control' => 'no-cache', + 'Content-Disposition' => 'attachment;filename=oss_download.log', + 'Content-Encoding' => 'utf-8', + 'Content-Language' => 'zh-CN', + 'x-oss-server-side-encryption' => 'AES256', + 'x-oss-meta-self-define-title' => 'user define meta info', + ), + ); + + try { + $this->ossClient->putObject($this->bucket, $object, $content, $options); + } catch (OssException $e) { + $this->assertFalse(true); + } + } +} diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientTest.php index 8898711dd..b7c676f5a 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssClientTest.php @@ -1,521 +1,346 @@ -credentials = new TestEmptyIdCredentials(); - } else if ($flag == 1) { - $this->credentials = new TestEmptySecretCredentials(); - } else { - $this->credentials = null; - } - } - - /** - * @return Credentials - */ - public function getCredentials() - { - return $this->credentials; - } -} - -class OssClientTest extends TestOssClientBase -{ - public function testConstrunct() - { - try { - $ossClient = new OssClient('id', 'key', 'http://oss-cn-hangzhou.aliyuncs.com'); - $this->assertFalse($ossClient->isUseSSL()); - $ossClient->setUseSSL(true); - $this->assertTrue($ossClient->isUseSSL()); - $this->assertTrue(true); - $this->assertEquals(3, $ossClient->getMaxRetries()); - $ossClient->setMaxTries(4); - $this->assertEquals(4, $ossClient->getMaxRetries()); - $ossClient->setTimeout(10); - $ossClient->setConnectTimeout(20); - } catch (OssException $e) { - assertFalse(true); - } - } - - public function testConstrunct2() - { - try { - $ossClient = new OssClient('id', "", 'http://oss-cn-hangzhou.aliyuncs.com'); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals("access key secret is empty", $e->getMessage()); - } - } - - public function testConstrunct3() - { - try { - $ossClient = new OssClient("", 'key', 'http://oss-cn-hangzhou.aliyuncs.com'); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals("access key id is empty", $e->getMessage()); - } - } - - public function testConstrunct4() - { - try { - $ossClient = new OssClient('id', 'key', ""); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('endpoint is empty', $e->getMessage()); - } - } - - public function testConstrunct5() - { - try { - $ossClient = new OssClient('id', 'key', "123.123.123.1"); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - } - - public function testConstrunct6() - { - try { - $ossClient = new OssClient('id', 'key', "https://123.123.123.1"); - $this->assertTrue($ossClient->isUseSSL()); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - - try { - $ossClient = new OssClient('id', 'key', "https://123.123.123.1:3128"); - $this->assertTrue($ossClient->isUseSSL()); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - } - - public function testConstrunct7() - { - try { - $ossClient = new OssClient('id', 'key', "http://123.123.123.1"); - $this->assertFalse($ossClient->isUseSSL()); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - - try { - $ossClient = new OssClient('id', 'key', "http://123.123.123.1:3128"); - $this->assertFalse($ossClient->isUseSSL()); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - } - - public function testConstrunct8() - { - try { - $ossClient = new OssClient('id', 'key', "http://123.123.123.1", true); - $ossClient->listBuckets(); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertFalse(false); - } - } - - public function testConstrunct9() - { - try { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - $ossClient->listBuckets(); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testConstrunct10() - { - try { - $ossClient = new OssClient('id', 'key', "http://ABC-COM.TEST.123.cn", true); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertTrue(false); - } - } - - public function testConstrunct11() - { - try { - $ossClient = new OssClient('id', 'key', "oss-test.com\\aliyuncs.com"); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('endpoint is invalid:' . "oss-test.com\\aliyuncs.com", $e->getMessage()); - } - } - - public function testConstrunct12() - { - try { - $ossClient = new OssClient('id', 'key', "192.168.1.0:abc123"); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('endpoint is invalid:' . "192.168.1.0:abc123", $e->getMessage()); - } - } - - public function testSupportPutEmptyObject() - { - try { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = $this->bucket; - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - $ossClient->putObject($bucket, 'test_emptybody', ''); - } catch (OssException $e) { - $this->assertFalse(true); - } - - //use invalid sts-token, should fail. - try { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = $this->bucket; - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, "invalid-sts-token"); - $ossClient->putObject($bucket, 'test_emptybody', ''); - $this->assertTrue(false); - } catch (OssException $e) { - $this->assertEquals('InvalidAccessKeyId', $e->getErrorCode()); - } - } - - public function testCreateObjectDir() - { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = $this->bucket; - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - - try { - $object = 'test-dir'; - $ossClient->createObjectDir($bucket, $object); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertFalse(true); - } - - try { - $object = '0'; - $ossClient->createObjectDir($bucket, $object); - $ossClient->putObject($bucket, $object, ''); - $this->assertTrue(true); - } catch (OssException $e) { - var_dump($e); - $this->assertFalse(true); - } - } - - public function testGetBucketCors() - { - try { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint(). '/ '; - $bucket = Common::getBucketName(); - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - $ossClient->getBucketCors($bucket); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testGetBucketCname() - { - try { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = $this->bucket; - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - $ossClient->getBucketCname($bucket); - $this->assertTrue(true); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testProxySupport() - { - $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = Common::getBucketName() . '-proxy'; - $requestProxy = getenv('OSS_PROXY'); - $key = 'test-proxy-srv-object'; - $content = 'test-content'; - $proxys = parse_url($requestProxy); - - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, null, $requestProxy); - - $result = $ossClient->createBucket($bucket); - $this->checkProxy($result, $proxys); - - $result = $ossClient->putObject($bucket, $key, $content); - $this->checkProxy($result, $proxys); - $result = $ossClient->getObject($bucket, $key); - $this->assertEquals($content, $result); - - // list object - $objectListInfo = $ossClient->listObjects($bucket); - $objectList = $objectListInfo->getObjectList(); - $this->assertNotNull($objectList); - $this->assertTrue(is_array($objectList)); - $objects = array(); - foreach ($objectList as $value) { - $objects[] = $value->getKey(); - } - $this->assertEquals(1, count($objects)); - $this->assertTrue(in_array($key, $objects)); - - $result = $ossClient->deleteObject($bucket, $key); - $this->checkProxy($result, $proxys); - - $result = $ossClient->deleteBucket($bucket); - $this->checkProxy($result, $proxys); - } - - private function checkProxy($result, $proxys) - { - $this->assertEquals($result['info']['primary_ip'], $proxys['host']); - $this->assertEquals($result['info']['primary_port'], $proxys['port']); - $this->assertTrue(array_key_exists('via', $result)); - } - - public function testIpEndpoint() - { - try { - $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = '192.168.1.1'; - $bucket = Common::getBucketName(); - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); - $object = "a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(strpos($signedUrl, '192.168.1.1/' . $bucket . '/a.file?') != false); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testCnameEndpoint() - { - try { - $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = 'cname.endpoint'; - $bucket = Common::getBucketName(); - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); - $object = "a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(strpos($signedUrl, 'cname.endpoint/a.file?') != false); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testStsToken() - { - try { - $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; - $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; - $endpoint = ' ' . Common::getEndpoint() . '/ '; - $bucket = Common::getBucketName(); - $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, "test-token"); - $object = "a.file"; - $timeout = 3600; - $options = array('Content-Type' => 'txt'); - $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); - $this->assertTrue(strpos($signedUrl, 'security-token=test-token') != false); - } catch (OssException $e) { - $this->assertFalse(true); - } - } - - public function testEmptyCredentials() - { - // empty case, should throw exception - try { - $id = ''; - $secret = 'accessKey_secret'; - $provider = new StaticCredentialsProvider($id, $secret); - $config = array( - 'provider' => $provider, - 'endpoint' => 'http://oss-cn-hangzhou.aliyuncs.com' - ); - $ossClient = new OssClient($config); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('access key id is empty', $e->getMessage()); - } - - // empty case, should throw exception - try { - $id = 'id'; - $secret = ''; - $provider = new StaticCredentialsProvider($id, $secret); - $config = array( - 'provider' => $provider, - 'endpoint' => 'http://oss-cn-hangzhou.aliyuncs.com' - ); - $ossClient = new OssClient($config); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('access key secret is empty', $e->getMessage()); - } - - // empty case, should throw exception - try { - $provider = new TestCredentialsProvider(0); - $config = array( - 'provider' => $provider, - 'endpoint' => 'http://oss-cn-hangzhou.aliyuncs.com' - ); - $ossClient = new OssClient($config); - $ossClient->getBucketAcl("bucket"); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('credentials is empty.', $e->getMessage()); - } - - // empty case, should throw exception - try { - $provider = new TestCredentialsProvider(1); - $config = array( - 'provider' => $provider, - 'endpoint' => 'http://oss-cn-hangzhou.aliyuncs.com' - ); - $ossClient = new OssClient($config); - $ossClient->getBucketAcl("bucket"); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('access key secret is empty', $e->getMessage()); - } - - // empty case, should throw exception - try { - $provider = new TestCredentialsProvider(2); - $config = array( - 'provider' => $provider, - 'endpoint' => 'http://oss-cn-hangzhou.aliyuncs.com' - ); - $ossClient = new OssClient($config); - $ossClient->getBucketAcl("bucket"); - $this->assertFalse(true); - } catch (OssException $e) { - $this->assertEquals('access key id is empty', $e->getMessage()); - } - } - - public function testEnvironmentVariableCredentialsProvider() - { - try { - $provider = new EnvironmentVariableCredentialsProvider(); - $config = array( - 'provider' => $provider, - 'endpoint' => Common::getEndpoint(), - ); - $ossClient = new OssClient($config); - $ossClient->putObject($this->bucket, 'test_emptybody', ''); - $this->assertTrue(true); - } catch (OssException $e) { - printf($e->getMessage()); - $this->assertFalse(true); - } - - - try { - $ossClient->getObject($this->bucket, 'test_emptybody'); - $this->assertTrue(true); - } catch (OssException $e) { - printf($e->getMessage()); - $this->assertFalse(true); - } - } -} +assertFalse($ossClient->isUseSSL()); + $ossClient->setUseSSL(true); + $this->assertTrue($ossClient->isUseSSL()); + $this->assertTrue(true); + $this->assertEquals(3, $ossClient->getMaxRetries()); + $ossClient->setMaxTries(4); + $this->assertEquals(4, $ossClient->getMaxRetries()); + $ossClient->setTimeout(10); + $ossClient->setConnectTimeout(20); + } catch (OssException $e) { + assertFalse(true); + } + } + + public function testConstrunct2() + { + try { + $ossClient = new OssClient('id', "", 'http://oss-cn-hangzhou.aliyuncs.com'); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals("access key secret is empty", $e->getMessage()); + } + } + + public function testConstrunct3() + { + try { + $ossClient = new OssClient("", 'key', 'http://oss-cn-hangzhou.aliyuncs.com'); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals("access key id is empty", $e->getMessage()); + } + } + + public function testConstrunct4() + { + try { + $ossClient = new OssClient('id', 'key', ""); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals('endpoint is empty', $e->getMessage()); + } + } + + public function testConstrunct5() + { + try { + $ossClient = new OssClient('id', 'key', "123.123.123.1"); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + } + + public function testConstrunct6() + { + try { + $ossClient = new OssClient('id', 'key', "https://123.123.123.1"); + $this->assertTrue($ossClient->isUseSSL()); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + + try { + $ossClient = new OssClient('id', 'key', "https://123.123.123.1:3128"); + $this->assertTrue($ossClient->isUseSSL()); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + } + + public function testConstrunct7() + { + try { + $ossClient = new OssClient('id', 'key', "http://123.123.123.1"); + $this->assertFalse($ossClient->isUseSSL()); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + + try { + $ossClient = new OssClient('id', 'key', "http://123.123.123.1:3128"); + $this->assertFalse($ossClient->isUseSSL()); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + } + + public function testConstrunct8() + { + try { + $ossClient = new OssClient('id', 'key', "http://123.123.123.1", true); + $ossClient->listBuckets(); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertFalse(false); + } + } + + public function testConstrunct9() + { + try { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); + $ossClient->listBuckets(); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testConstrunct10() + { + try { + $ossClient = new OssClient('id', 'key', "http://ABC-COM.TEST.123.cn", true); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertTrue(false); + } + } + + public function testConstrunct11() + { + try { + $ossClient = new OssClient('id', 'key', "oss-test.com\\aliyuncs.com"); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals('endpoint is invalid:'."oss-test.com\\aliyuncs.com", $e->getMessage()); + } + } + + public function testConstrunct12() + { + try { + $ossClient = new OssClient('id', 'key', "192.168.1.0:abc123"); + $this->assertFalse(true); + } catch (OssException $e) { + $this->assertEquals('endpoint is invalid:'."192.168.1.0:abc123", $e->getMessage()); + } + } + + public function testSupportPutEmptyObject() + { + try { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = $this->bucket; + $ossClient = new OssClient($accessKeyId, $accessKeySecret , $endpoint, false); + $ossClient->putObject($bucket,'test_emptybody',''); + } catch (OssException $e) { + $this->assertFalse(true); + } + + //use invalid sts-token, should fail. + try { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = $this->bucket; + $ossClient = new OssClient($accessKeyId, $accessKeySecret , $endpoint, false, "invalid-sts-token"); + $ossClient->putObject($bucket,'test_emptybody',''); + $this->assertTrue(false); + } catch (OssException $e) { + $this->assertEquals('InvalidAccessKeyId', $e->getErrorCode()); + } + } + + public function testCreateObjectDir() + { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = $this->bucket; + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); + + try { + $object='test-dir'; + $ossClient->createObjectDir($bucket,$object); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertFalse(true); + } + + try { + $object='0'; + $ossClient->createObjectDir($bucket,$object); + $ossClient->putObject($bucket,$object, ''); + $this->assertTrue(true); + } catch (OssException $e) { + var_dump($e); + $this->assertFalse(true); + } + } + + public function testGetBucketCors() + { + try { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = getenv('OSS_BUCKET'); + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); + $ossClient->getBucketCors($bucket); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testGetBucketCname() + { + try { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = $this->bucket; + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); + $ossClient->getBucketCname($bucket); + $this->assertTrue(true); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testProxySupport() + { + $accessKeyId = ' ' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = getenv('OSS_BUCKET') . '-proxy'; + $requestProxy = getenv('OSS_PROXY'); + $key = 'test-proxy-srv-object'; + $content = 'test-content'; + $proxys = parse_url($requestProxy); + + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, null, $requestProxy); + + $result = $ossClient->createBucket($bucket); + $this->checkProxy($result, $proxys); + + $result = $ossClient->putObject($bucket, $key, $content); + $this->checkProxy($result, $proxys); + $result = $ossClient->getObject($bucket, $key); + $this->assertEquals($content, $result); + + // list object + $objectListInfo = $ossClient->listObjects($bucket); + $objectList = $objectListInfo->getObjectList(); + $this->assertNotNull($objectList); + $this->assertTrue(is_array($objectList)); + $objects = array(); + foreach ($objectList as $value) { + $objects[] = $value->getKey(); + } + $this->assertEquals(1, count($objects)); + $this->assertTrue(in_array($key, $objects)); + + $result = $ossClient->deleteObject($bucket, $key); + $this->checkProxy($result,$proxys); + + $result = $ossClient->deleteBucket($bucket); + $this->checkProxy($result, $proxys); + } + + private function checkProxy($result, $proxys) + { + $this->assertEquals($result['info']['primary_ip'], $proxys['host']); + $this->assertEquals($result['info']['primary_port'], $proxys['port']); + $this->assertTrue(array_key_exists('via', $result)); + } + + public function testIpEndpoint() + { + try { + $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = '192.168.1.1'; + $bucket = getenv('OSS_BUCKET'); + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false); + $object = "a.file"; + $timeout = 3600; + $options = array('Content-Type' => 'txt'); + $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); + $this->assertTrue(strpos($signedUrl, '192.168.1.1/skyranch-php-test/a.file?') != false); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testCnameEndpoint() + { + try { + $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = 'cname.endpoint'; + $bucket = getenv('OSS_BUCKET'); + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + $object = "a.file"; + $timeout = 3600; + $options = array('Content-Type' => 'txt'); + $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); + $this->assertTrue(strpos($signedUrl, 'cname.endpoint/a.file?') != false); + } catch (OssException $e) { + $this->assertFalse(true); + } + } + + public function testStsToken() + { + try { + $accessKeyId = 'sk' . getenv('OSS_ACCESS_KEY_ID') . ' '; + $accessKeySecret = ' ' . getenv('OSS_ACCESS_KEY_SECRET') . ' '; + $endpoint = ' ' . getenv('OSS_ENDPOINT') . '/ '; + $bucket = getenv('OSS_BUCKET'); + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, "test-token"); + $object = "a.file"; + $timeout = 3600; + $options = array('Content-Type' => 'txt'); + $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", $options); + $this->assertTrue(strpos($signedUrl, 'security-token=test-token') != false); + } catch (OssException $e) { + $this->assertFalse(true); + } + } +} diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssUtilTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssUtilTest.php index 6d6196c4f..598a7cc56 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssUtilTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/OssUtilTest.php @@ -143,7 +143,7 @@ BBBB; public function testReadDir() { - $list = OssUtil::readDir(__DIR__, ".|..|.svn|.git", true); + $list = OssUtil::readDir("./src", ".|..|.svn|.git", true); $this->assertNotNull($list); } diff --git a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/PutSetDeleteResultTest.php b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/PutSetDeleteResultTest.php index c87955e90..202f173f1 100644 --- a/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/PutSetDeleteResultTest.php +++ b/src/vendor/aliyuncs/oss-sdk-php/tests/OSS/Tests/PutSetDeleteResultTest.php @@ -6,7 +6,7 @@ use OSS\Core\OssException; use OSS\Http\ResponseCore; use OSS\Result\PutSetDeleteResult; -class PutSetDeleteResultTest extends \PHPUnit\Framework\TestCase +class ResultTest extends \PHPUnit\Framework\TestCase { public function testNullResponse() diff --git a/src/vendor/composer/autoload_psr4.php b/src/vendor/composer/autoload_psr4.php index 6d496b001..d41f961ed 100644 --- a/src/vendor/composer/autoload_psr4.php +++ b/src/vendor/composer/autoload_psr4.php @@ -11,10 +11,10 @@ return array( 'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'), 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), 'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'), - 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-queue/src', $vendorDir . '/topthink/think-template/src'), + 'think\\' => array($vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-queue/src'), 'thans\\filesystem\\' => array($vendorDir . '/thans/thinkphp-filesystem-cloud/src'), 'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), - 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), + 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'), 'liliuwei\\think\\' => array($vendorDir . '/liliuwei/thinkphp-jump/src'), 'extend\\' => array($baseDir . '/extend'), 'app\\' => array($baseDir . '/app'), @@ -42,7 +42,7 @@ return array( 'Qcloud\\Cos\\' => array($vendorDir . '/qcloud/cos-sdk-v5/src'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), diff --git a/src/vendor/composer/autoload_static.php b/src/vendor/composer/autoload_static.php index dae80959f..3eb591627 100644 --- a/src/vendor/composer/autoload_static.php +++ b/src/vendor/composer/autoload_static.php @@ -191,11 +191,11 @@ class ComposerStaticInit516d2ac39a060b91610bddcc729d2cf4 ), 'think\\' => array ( - 0 => __DIR__ . '/..' . '/topthink/framework/src/think', + 0 => __DIR__ . '/..' . '/topthink/think-template/src', 1 => __DIR__ . '/..' . '/topthink/think-helper/src', 2 => __DIR__ . '/..' . '/topthink/think-orm/src', - 3 => __DIR__ . '/..' . '/topthink/think-queue/src', - 4 => __DIR__ . '/..' . '/topthink/think-template/src', + 3 => __DIR__ . '/..' . '/topthink/framework/src/think', + 4 => __DIR__ . '/..' . '/topthink/think-queue/src', ), 'thans\\filesystem\\' => array ( @@ -208,8 +208,8 @@ class ComposerStaticInit516d2ac39a060b91610bddcc729d2cf4 'phpDocumentor\\Reflection\\' => array ( 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', - 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', - 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', + 1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', + 2 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', ), 'liliuwei\\think\\' => array ( @@ -321,8 +321,8 @@ class ComposerStaticInit516d2ac39a060b91610bddcc729d2cf4 ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-factory/src', - 1 => __DIR__ . '/..' . '/psr/http-message/src', + 0 => __DIR__ . '/..' . '/psr/http-message/src', + 1 => __DIR__ . '/..' . '/psr/http-factory/src', ), 'Psr\\Http\\Client\\' => array ( diff --git a/src/vendor/composer/installed.json b/src/vendor/composer/installed.json index 14bfefc1f..dfe66845b 100644 --- a/src/vendor/composer/installed.json +++ b/src/vendor/composer/installed.json @@ -6272,20 +6272,6 @@ "support": { "source": "https://github.com/symfony/var-dumper/tree/v4.4.41" }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "install-path": "../symfony/var-dumper" }, { @@ -6876,7 +6862,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-trace/zipball/9a9fa8f767b6c66c5a133ad21ca1bc96ad329444", "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0", @@ -6886,12 +6878,12 @@ "type": "library", "extra": { "think": { - "config": { - "trace": "src/config.php" - }, "services": [ "think\\trace\\Service" - ] + ], + "config": { + "trace": "src/config.php" + } } }, "installation-source": "dist", @@ -6911,10 +6903,6 @@ } ], "description": "thinkphp debug trace", - "support": { - "issues": "https://github.com/top-think/think-trace/issues", - "source": "https://github.com/top-think/think-trace/tree/v1.4" - }, "install-path": "../topthink/think-trace" }, { diff --git a/src/vendor/composer/installed.php b/src/vendor/composer/installed.php index c2b0888e9..29ac800f0 100644 --- a/src/vendor/composer/installed.php +++ b/src/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'topthink/think', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => 'e0aeea15f212c8fd39c805cda2d8616e4f4a6a29', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -908,9 +908,9 @@ 'dev_requirement' => false, ), 'topthink/think' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => 'e0aeea15f212c8fd39c805cda2d8616e4f4a6a29', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/src/vendor/dragonmantank/cron-expression/README.md b/src/vendor/dragonmantank/cron-expression/README.md index b9df3db5f..494652c84 100644 --- a/src/vendor/dragonmantank/cron-expression/README.md +++ b/src/vendor/dragonmantank/cron-expression/README.md @@ -1,7 +1,7 @@ PHP Cron Expression Parser ========================== -[![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Tests](https://github.com/dragonmantank/cron-expression/actions/workflows/tests.yml/badge.svg)](https://github.com/dragonmantank/cron-expression/actions/workflows/tests.yml) [![StyleCI](https://github.styleci.io/repos/103715337/shield?branch=master)](https://github.styleci.io/repos/103715337) +[![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Build Status](https://secure.travis-ci.org/dragonmantank/cron-expression.png)](http://travis-ci.org/dragonmantank/cron-expression) [![StyleCI](https://github.styleci.io/repos/103715337/shield?branch=master)](https://github.styleci.io/repos/103715337) The PHP cron expression parser can parse a CRON expression, determine if it is due to run, calculate the next run date of the expression, and calculate the previous @@ -55,65 +55,23 @@ CRON Expressions A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows: -``` -* * * * * -- - - - - -| | | | | -| | | | | -| | | | +----- day of week (0-7) (Sunday = 0 or 7) (or SUN-SAT) -| | | +--------- month (1-12) (or JAN-DEC) -| | +------------- day of month (1-31) -| +----------------- hour (0-23) -+--------------------- minute (0-59) -``` + * * * * * + - - - - - + | | | | | + | | | | | + | | | | +----- day of week (0 - 7) (Sunday=0 or 7) + | | | +---------- month (1 - 12) + | | +--------------- day of month (1 - 31) + | +-------------------- hour (0 - 23) + +------------------------- min (0 - 59) -Each part of expression can also use wildcard, lists, ranges and steps: +This library also supports a few macros: -- wildcard - match always - - `* * * * *` - At every minute. - - day of week and day of month also support `?`, an alias to `*` -- lists - match list of values, ranges and steps - - e.g. `15,30 * * * *` - At minute 15 and 30. -- ranges - match values in range - - e.g. `1-9 * * * *` - At every minute from 1 through 9. -- steps - match every nth value in range - - e.g. `*/5 * * * *` - At every 5th minute. - - e.g. `0-30/5 * * * *` - At every 5th minute from 0 through 30. -- combinations - - e.g. `0-14,30-44 * * * *` - At every minute from 0 through 14 and every minute from 30 through 44. - -You can also use macro instead of an expression: - -- `@yearly`, `@annually` - At 00:00 on 1st of January. (same as `0 0 1 1 *`) -- `@monthly` - At 00:00 on day-of-month 1. (same as `0 0 1 * *`) -- `@weekly` - At 00:00 on Sunday. (same as `0 0 * * 0`) -- `@daily`, `@midnight` - At 00:00. (same as `0 0 * * *`) -- `@hourly` - At minute 0. (same as `0 * * * *`) - -Day of month extra features: - -- nearest weekday - weekday (Monday-Friday) nearest to the given day - - e.g. `* * 15W * *` - At every minute on a weekday nearest to the 15th. - - If you were to specify `15W` as the value, the meaning is: "the nearest weekday to the 15th of the month" - So if the 15th is a Saturday, the trigger will fire on Friday the 14th. - If the 15th is a Sunday, the trigger will fire on Monday the 16th. - If the 15th is a Tuesday, then it will fire on Tuesday the 15th. - - However, if you specify `1W` as the value for day-of-month, - and the 1st is a Saturday, the trigger will fire on Monday the 3rd, - as it will not 'jump' over the boundary of a month's days. -- last day of the month - - e.g. `* * L * *` - At every minute on a last day-of-month. -- last weekday of the month - - e.g. `* * LW * *` - At every minute on a last weekday. - -Day of week extra features: - -- nth day - - e.g. `* * * * 7#4` - At every minute on 4th Sunday. - - 1-5 - - Every day of week repeats 4-5 times a month. To target the last one, use "last day" feature instead. -- last day - - e.g. `* * * * 7L` - At every minute on the last Sunday. +* `@yearly`, `@annually` - Run once a year, midnight, Jan. 1 - `0 0 1 1 *` +* `@monthly` - Run once a month, midnight, first of month - `0 0 1 * *` +* `@weekly` - Run once a week, midnight on Sun - `0 0 * * 0` +* `@daily`, `@midnight` - Run once a day, midnight - `0 0 * * *` +* `@hourly` - Run once an hour, first minute - `0 * * * *` Requirements ============ @@ -127,5 +85,3 @@ Projects that Use cron-expression * Part of the [Laravel Framework](https://github.com/laravel/framework/) * Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle) * Framework agnostic, PHP-based job scheduler - [Crunz](https://github.com/crunzphp/crunz) -* Framework agnostic job scheduler - with locks, parallelism, per-second scheduling and more - [orisai/scheduler](https://github.com/orisai/scheduler) -* Explain expression in English (and other languages) with [orisai/cron-expression-explainer](https://github.com/orisai/cron-expression-explainer) diff --git a/src/vendor/dragonmantank/cron-expression/composer.json b/src/vendor/dragonmantank/cron-expression/composer.json index fdb46ee41..657a5b47c 100644 --- a/src/vendor/dragonmantank/cron-expression/composer.json +++ b/src/vendor/dragonmantank/cron-expression/composer.json @@ -18,6 +18,7 @@ "require-dev": { "phpstan/phpstan": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0", + "phpstan/phpstan-webmozart-assert": "^1.0", "phpstan/extension-installer": "^1.0" }, "autoload": { @@ -37,11 +38,6 @@ "phpstan": "./vendor/bin/phpstan analyze", "test": "phpunit" }, - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "config": { "allow-plugins": { "ocramius/package-versions": true, diff --git a/src/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php b/src/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php index f3d8eb003..216ce432f 100644 --- a/src/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php +++ b/src/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php @@ -12,6 +12,7 @@ use Exception; use InvalidArgumentException; use LogicException; use RuntimeException; +use Webmozart\Assert\Assert; /** * CRON expression parser that can determine whether or not a CRON expression is @@ -147,7 +148,7 @@ class CronExpression /** * @deprecated since version 3.0.2, use __construct instead. */ - public static function factory(string $expression, ?FieldFactoryInterface $fieldFactory = null): CronExpression + public static function factory(string $expression, FieldFactoryInterface $fieldFactory = null): CronExpression { /** @phpstan-ignore-next-line */ return new static($expression, $fieldFactory); @@ -178,7 +179,7 @@ class CronExpression * @param null|FieldFactoryInterface $fieldFactory Factory to create cron fields * @throws InvalidArgumentException */ - public function __construct(string $expression, ?FieldFactoryInterface $fieldFactory = null) + public function __construct(string $expression, FieldFactoryInterface $fieldFactory = null) { $shortcut = strtolower($expression); $expression = self::$registeredAliases[$shortcut] ?? $expression; @@ -199,12 +200,7 @@ class CronExpression public function setExpression(string $value): CronExpression { $split = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY); - - if (!\is_array($split)) { - throw new InvalidArgumentException( - $value . ' is not a valid CRON expression' - ); - } + Assert::isArray($split); $notEnoughParts = \count($split) < 5; @@ -338,10 +334,7 @@ class CronExpression $currentTime = new DateTime($currentTime); } - if (!$currentTime instanceof DateTime) { - throw new InvalidArgumentException('invalid current time'); - } - + Assert::isInstanceOf($currentTime, DateTime::class); $currentTime->setTimezone(new DateTimeZone($timeZone)); $matches = []; @@ -427,10 +420,7 @@ class CronExpression $currentTime = new DateTime($currentTime); } - if (!$currentTime instanceof DateTime) { - throw new InvalidArgumentException('invalid current time'); - } - + Assert::isInstanceOf($currentTime, DateTime::class); $currentTime->setTimezone(new DateTimeZone($timeZone)); // drop the seconds to 0 @@ -472,10 +462,7 @@ class CronExpression $currentDate = new DateTime('now'); } - if (!$currentDate instanceof DateTime) { - throw new InvalidArgumentException('invalid current date'); - } - + Assert::isInstanceOf($currentDate, DateTime::class); $currentDate->setTimezone(new DateTimeZone($timeZone)); // Workaround for setTime causing an offset change: https://bugs.php.net/bug.php?id=81074 $currentDate = DateTime::createFromFormat("!Y-m-d H:iO", $currentDate->format("Y-m-d H:iP"), $currentDate->getTimezone()); diff --git a/src/vendor/ezyang/htmlpurifier/CHANGELOG.md b/src/vendor/ezyang/htmlpurifier/CHANGELOG.md new file mode 100644 index 000000000..55cb9029c --- /dev/null +++ b/src/vendor/ezyang/htmlpurifier/CHANGELOG.md @@ -0,0 +1,6 @@ +# [4.16.0](https://github.com/ezyang/htmlpurifier/compare/v4.15.0...v4.16.0) (2022-09-18) + + +### Features + +* add semantic release ([#307](https://github.com/ezyang/htmlpurifier/issues/307)) ([db31243](https://github.com/ezyang/htmlpurifier/commit/db312435cb9d8d73395f75f9642a43ba6de5e903)), closes [#322](https://github.com/ezyang/htmlpurifier/issues/322) [#323](https://github.com/ezyang/htmlpurifier/issues/323) [#326](https://github.com/ezyang/htmlpurifier/issues/326) [#327](https://github.com/ezyang/htmlpurifier/issues/327) [#328](https://github.com/ezyang/htmlpurifier/issues/328) [#329](https://github.com/ezyang/htmlpurifier/issues/329) [#330](https://github.com/ezyang/htmlpurifier/issues/330) [#331](https://github.com/ezyang/htmlpurifier/issues/331) [#332](https://github.com/ezyang/htmlpurifier/issues/332) [#333](https://github.com/ezyang/htmlpurifier/issues/333) [#337](https://github.com/ezyang/htmlpurifier/issues/337) [#335](https://github.com/ezyang/htmlpurifier/issues/335) [ezyang/htmlpurifier#334](https://github.com/ezyang/htmlpurifier/issues/334) [#336](https://github.com/ezyang/htmlpurifier/issues/336) [#338](https://github.com/ezyang/htmlpurifier/issues/338) diff --git a/src/vendor/ezyang/htmlpurifier/VERSION b/src/vendor/ezyang/htmlpurifier/VERSION index 35e3d1bab..f029ee574 100644 --- a/src/vendor/ezyang/htmlpurifier/VERSION +++ b/src/vendor/ezyang/htmlpurifier/VERSION @@ -1 +1 @@ -4.19.0 \ No newline at end of file +4.15.0 \ No newline at end of file diff --git a/src/vendor/ezyang/htmlpurifier/composer.json b/src/vendor/ezyang/htmlpurifier/composer.json index cfb715174..d75582950 100644 --- a/src/vendor/ezyang/htmlpurifier/composer.json +++ b/src/vendor/ezyang/htmlpurifier/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -38,8 +38,7 @@ "repositories": [ { "type": "vcs", - "url": "https://github.com/ezyang/simpletest.git", - "no-api": true + "url": "https://github.com/ezyang/simpletest.git" } ] } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php index 1f99a4aa2..47ee0133d 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php @@ -7,7 +7,7 @@ * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS * FILE, changes will be overwritten the next time the script is run. * - * @version 4.19.0 + * @version 4.15.0 * * @warning * You must *not* include any other HTML Purifier files before this file, @@ -101,7 +101,6 @@ require 'HTMLPurifier/AttrDef/CSS/Length.php'; require 'HTMLPurifier/AttrDef/CSS/ListStyle.php'; require 'HTMLPurifier/AttrDef/CSS/Multiple.php'; require 'HTMLPurifier/AttrDef/CSS/Percentage.php'; -require 'HTMLPurifier/AttrDef/CSS/Ratio.php'; require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php'; require 'HTMLPurifier/AttrDef/CSS/URI.php'; require 'HTMLPurifier/AttrDef/HTML/Bool.php'; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php index 31b5a0f79..26f061276 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php @@ -19,7 +19,7 @@ */ /* - HTML Purifier 4.19.0 - Standards Compliant HTML Filtering + HTML Purifier 4.15.0 - Standards Compliant HTML Filtering Copyright (C) 2006-2008 Edward Z. Yang This library is free software; you can redistribute it and/or @@ -58,12 +58,12 @@ class HTMLPurifier * Version of HTML Purifier. * @type string */ - public $version = '4.19.0'; + public $version = '4.15.0'; /** * Constant with version of HTML Purifier. */ - const VERSION = '4.19.0'; + const VERSION = '4.15.0'; /** * Global configuration object. diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php index 8a417d246..94543f593 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php @@ -95,7 +95,6 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php'; -require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ratio.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php'; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php index af6b8a05d..ad2cb90ad 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php @@ -27,13 +27,6 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef $definition = $config->getCSSDefinition(); $allow_duplicates = $config->get("CSS.AllowDuplicates"); - $universal_attrdef = new HTMLPurifier_AttrDef_Enum( - array( - 'initial', - 'inherit', - 'unset', - ) - ); // According to the CSS2.1 spec, the places where a // non-delimiting semicolon can appear are in strings @@ -103,13 +96,16 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef if (!$ok) { continue; } - $result = $universal_attrdef->validate($value, $config, $context); - if ($result === false) { + // inefficient call, since the validator will do this again + if (strtolower(trim($value)) !== 'inherit') { + // inherit works for everything (but only on the base property) $result = $definition->info[$property]->validate( $value, $config, $context ); + } else { + $result = 'inherit'; } if ($result === false) { continue; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php index 799166bb9..74e24c881 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php @@ -10,21 +10,23 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef public function __construct() { - // Lowercase letters - $l = range('a', 'z'); - // Uppercase letters - $u = range('A', 'Z'); - // Digits - $d = range('0', '9'); - // Special bytes used by UTF-8 - $b = array_map('chr', range(0x80, 0xFF)); - // All valid characters for the mask - $c = array_merge($l, $u, $d, $b); - // Concatenate all valid characters into a string - // Use '_- ' as an initial value - $this->mask = array_reduce($c, function ($carry, $value) { - return $carry . $value; - }, '_- '); + $this->mask = '_- '; + for ($c = 'a'; $c <= 'z'; $c++) { + $this->mask .= $c; + } + for ($c = 'A'; $c <= 'Z'; $c++) { + $this->mask .= $c; + } + for ($c = '0'; $c <= '9'; $c++) { + $this->mask .= $c; + } // cast-y, but should be fine + // special bytes used by UTF-8 + for ($i = 0x80; $i <= 0xFF; $i++) { + // We don't bother excluding invalid bytes in this range, + // because the our restriction of well-formed UTF-8 will + // prevent these from ever occurring. + $this->mask .= chr($i); + } /* PHP's internal strcspn implementation is @@ -195,7 +197,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef // transforms don't pose a security risk (as \\ and \" // might--these escapes are not supported by most browsers). // We could try to be clever and use single-quote wrapping - // when there is a double quote present, but I have chosen + // when there is a double quote present, but I have choosen // not to implement that. (NOTE: you can reduce the amount // of escapes by one depending on what quoting style you use) // $font = str_replace('\\', '\\5C ', $font); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php index 3decf0c45..63fa04c15 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php @@ -25,7 +25,12 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef 'rev' => 'AllowedRev' ); if (!isset($configLookup[$name])) { - throw new Exception('Unrecognized attribute name for link relationship.'); + trigger_error( + 'Unrecognized attribute name for link ' . + 'relationship.', + E_USER_ERROR + ); + return; } $this->name = $configLookup[$name]; } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php index 17a97c1ec..1beeaa5d2 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php @@ -63,18 +63,24 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef // This doesn't match I18N domain names, but we don't have proper IRI support, // so force users to insert Punycode. - // Underscores defined as Unreserved Characters in RFC 3986 are - // allowed in a URI. There are cases where we want to consider a - // URI containing "_" such as "_dmarc.example.com". - // Underscores are not allowed in the default. If you want to - // allow it, set Core.AllowHostnameUnderscore to true. + // There is not a good sense in which underscores should be + // allowed, since it's technically not! (And if you go as + // far to allow everything as specified by the DNS spec... + // well, that's literally everything, modulo some space limits + // for the components and the overall name (which, by the way, + // we are NOT checking!). So we (arbitrarily) decide this: + // let's allow underscores wherever we would have allowed + // hyphens, if they are enabled. This is a pretty good match + // for browser behavior, for example, a large number of browsers + // cannot handle foo_.example.com, but foo_bar.example.com is + // fairly well supported. $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : ''; // Based off of RFC 1738, but amended so that // as per RFC 3696, the top label need only not be all numeric. // The productions describing this are: $a = '[a-z]'; // alpha - $an = "[a-z0-9$underscore]"; // alphanum + $an = '[a-z0-9]'; // alphanum $and = "[a-z0-9-$underscore]"; // alphanum | "-" // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum $domainlabel = "$an(?:$and*$an)?"; @@ -100,7 +106,7 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef // If we have Net_IDNA2 support, we can support IRIs by // punycoding them. (This is the most portable thing to do, // since otherwise we have to assume browsers support - } elseif ($config->get('Core.EnableIDNA') && class_exists('Net_IDNA2')) { + } elseif ($config->get('Core.EnableIDNA')) { $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true)); // we need to encode each period separately $parts = explode('.', $string); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php index dc4ef62ee..f243793ee 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php @@ -37,7 +37,7 @@ class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4 } } - // IPv4-compatibility check + // IPv4-compatiblity check if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) { $aIP = substr($aIP, 0, 0 - strlen($find[0])); $ip = explode('.', $find[0]); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php index d769c6fd2..d66c04a5b 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php @@ -3,7 +3,7 @@ // this MUST be placed in post, as it assumes that any value in dir is valid /** - * Post-transform that ensures that bdo tags have the dir attribute set. + * Post-trasnform that ensures that bdo tags have the dir attribute set. */ class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform { diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php index cc30ab8c3..dd63ea89c 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php @@ -33,11 +33,7 @@ class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform // XXX Kind of inefficient $url = $this->parser->parse($attr['href']); - - // Ignore invalid schemes (e.g. `javascript:`) - if (!($scheme = $url->getSchemeObj($config, $context))) { - return $attr; - } + $scheme = $url->getSchemeObj($config, $context); if ($scheme->browsable && !$url->isBenign($config, $context)) { $attr['target'] = '_blank'; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php index 62575ca65..e4429e86d 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php @@ -77,7 +77,7 @@ class HTMLPurifier_AttrTypes } if (!isset($this->info[$type])) { - throw new Exception('Cannot retrieve undefined attribute type ' . $type); + trigger_error('Cannot retrieve undefined attribute type ' . $type, E_USER_ERROR); return; } return $this->info[$type]->make($string); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php index 350330bb5..f97dc93ed 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php @@ -135,7 +135,7 @@ class HTMLPurifier_AttrValidator // we'd also want slightly more complicated substitution // involving an array as the return value, // although we're not sure how colliding attributes would - // resolve (certain ones would be completely overridden, + // resolve (certain ones would be completely overriden, // others would prepend themselves). } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php index 8805eccff..707122bb2 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php @@ -5,7 +5,7 @@ if (!defined('HTMLPURIFIER_PREFIX')) { define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..')); } -// accommodations for versions earlier than 5.0.2 +// accomodations for versions earlier than 5.0.2 // borrowed from PHP_Compat, LGPL licensed, by Aidan Lister if (!defined('PHP_EOL')) { switch (strtoupper(substr(PHP_OS, 0, 3))) { @@ -79,11 +79,44 @@ class HTMLPurifier_Bootstrap public static function registerAutoload() { $autoload = array('HTMLPurifier_Bootstrap', 'autoload'); - if (spl_autoload_functions() === false) { + if (($funcs = spl_autoload_functions()) === false) { spl_autoload_register($autoload); - } else { - // prepend flag exists, no need for shenanigans - spl_autoload_register($autoload, true, true); + } elseif (function_exists('spl_autoload_unregister')) { + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + // prepend flag exists, no need for shenanigans + spl_autoload_register($autoload, true, true); + } else { + $buggy = version_compare(PHP_VERSION, '5.2.11', '<'); + $compat = version_compare(PHP_VERSION, '5.1.2', '<=') && + version_compare(PHP_VERSION, '5.1.0', '>='); + foreach ($funcs as $func) { + if ($buggy && is_array($func)) { + // :TRICKY: There are some compatibility issues and some + // places where we need to error out + $reflector = new ReflectionMethod($func[0], $func[1]); + if (!$reflector->isStatic()) { + throw new Exception( + 'HTML Purifier autoloader registrar is not compatible + with non-static object methods due to PHP Bug #44144; + Please do not use HTMLPurifier.autoload.php (or any + file that includes this file); instead, place the code: + spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\')) + after your own autoloaders.' + ); + } + // Suprisingly, spl_autoload_register supports the + // Class::staticMethod callback format, although call_user_func doesn't + if ($compat) { + $func = implode('::', $func); + } + } + spl_autoload_unregister($func); + } + spl_autoload_register($autoload); + foreach ($funcs as $func) { + spl_autoload_register($func); + } + } } } } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php index 923d6f3d0..3f08b81c5 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php @@ -13,7 +13,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition * Assoc array of attribute name to definition object. * @type HTMLPurifier_AttrDef[] */ - public $info = []; + public $info = array(); /** * Constructs the info array. The meat of this class. @@ -22,12 +22,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition protected function doSetup($config) { $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum( - ['left', 'right', 'center', 'justify'], - false - ); - - $this->info['direction'] = new HTMLPurifier_AttrDef_Enum( - ['ltr', 'rtl'], + array('left', 'right', 'center', 'justify'), false ); @@ -36,7 +31,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['border-right-style'] = $this->info['border-left-style'] = $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum( - [ + array( 'none', 'hidden', 'dotted', @@ -47,42 +42,42 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'ridge', 'inset', 'outset' - ], + ), false ); $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style); $this->info['clear'] = new HTMLPurifier_AttrDef_Enum( - ['none', 'left', 'right', 'both'], + array('none', 'left', 'right', 'both'), false ); $this->info['float'] = new HTMLPurifier_AttrDef_Enum( - ['none', 'left', 'right'], + array('none', 'left', 'right'), false ); $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum( - ['normal', 'italic', 'oblique'], + array('normal', 'italic', 'oblique'), false ); $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum( - ['normal', 'small-caps'], + array('normal', 'small-caps'), false ); $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['none']), + array( + new HTMLPurifier_AttrDef_Enum(array('none')), new HTMLPurifier_AttrDef_CSS_URI() - ] + ) ); $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum( - ['inside', 'outside'], + array('inside', 'outside'), false ); $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum( - [ + array( 'disc', 'circle', 'square', @@ -92,7 +87,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'lower-alpha', 'upper-alpha', 'none' - ], + ), false ); $this->info['list-style-image'] = $uri_or_none; @@ -100,32 +95,34 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config); $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum( - ['capitalize', 'uppercase', 'lowercase', 'none'], + array('capitalize', 'uppercase', 'lowercase', 'none'), false ); $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color(); $this->info['background-image'] = $uri_or_none; $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum( - ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] + array('repeat', 'repeat-x', 'repeat-y', 'no-repeat') ); $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum( - ['scroll', 'fixed'] + array('scroll', 'fixed') ); $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition(); $this->info['background-size'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_Enum( - [ + array( 'auto', 'cover', 'contain', - ] + 'initial', + 'inherit', + ) ), new HTMLPurifier_AttrDef_CSS_Percentage(), new HTMLPurifier_AttrDef_CSS_Length() - ] + ) ); $border_color = @@ -134,10 +131,10 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['border-left-color'] = $this->info['border-right-color'] = $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['transparent']), + array( + new HTMLPurifier_AttrDef_Enum(array('transparent')), new HTMLPurifier_AttrDef_CSS_Color() - ] + ) ); $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config); @@ -149,32 +146,32 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['border-bottom-width'] = $this->info['border-left-width'] = $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['thin', 'medium', 'thick']), + array( + new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')), new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative - ] + ) ); $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width); $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['normal']), + array( + new HTMLPurifier_AttrDef_Enum(array('normal')), new HTMLPurifier_AttrDef_CSS_Length() - ] + ) ); $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['normal']), + array( + new HTMLPurifier_AttrDef_Enum(array('normal')), new HTMLPurifier_AttrDef_CSS_Length() - ] + ) ); $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_Enum( - [ + array( 'xx-small', 'x-small', 'small', @@ -184,20 +181,20 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'xx-large', 'larger', 'smaller' - ] + ) ), new HTMLPurifier_AttrDef_CSS_Percentage(), new HTMLPurifier_AttrDef_CSS_Length() - ] + ) ); $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ - new HTMLPurifier_AttrDef_Enum(['normal']), + array( + new HTMLPurifier_AttrDef_Enum(array('normal')), new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true) - ] + ) ); $margin = @@ -205,11 +202,11 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['margin-bottom'] = $this->info['margin-left'] = $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(['auto']) - ] + new HTMLPurifier_AttrDef_Enum(array('auto')) + ) ); $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin); @@ -220,40 +217,41 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['padding-bottom'] = $this->info['padding-left'] = $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true) - ] + ) ); $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding); $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage() - ] + ) ); $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(['auto']) - ] + new HTMLPurifier_AttrDef_Enum(array('auto', 'initial', 'inherit')) + ) ); $trusted_min_wh = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - ] + new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit')) + ) ); $trusted_max_wh = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true), - new HTMLPurifier_AttrDef_Enum(['none']) - ] + new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit')) + ) ); $max = $config->get('CSS.MaxImgLength'); @@ -265,10 +263,10 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'img', // For img tags: new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(['auto']) - ] + new HTMLPurifier_AttrDef_Enum(array('auto')) + ) ), // For everyone else: $trusted_wh @@ -280,7 +278,12 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition new HTMLPurifier_AttrDef_Switch( 'img', // For img tags: - new HTMLPurifier_AttrDef_CSS_Length('0', $max), + new HTMLPurifier_AttrDef_CSS_Composite( + array( + new HTMLPurifier_AttrDef_CSS_Length('0', $max), + new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit')) + ) + ), // For everyone else: $trusted_min_wh ); @@ -292,46 +295,22 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'img', // For img tags: new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length('0', $max), - new HTMLPurifier_AttrDef_Enum(['none']) - ] + new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit')) + ) ), // For everyone else: $trusted_max_wh ); - $this->info['aspect-ratio'] = new HTMLPurifier_AttrDef_CSS_Multiple( - new HTMLPurifier_AttrDef_CSS_Composite([ - new HTMLPurifier_AttrDef_CSS_Ratio(), - new HTMLPurifier_AttrDef_Enum(['auto']), - ]) - ); - - // text-decoration and related shorthands $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration(); - $this->info['text-decoration-line'] = new HTMLPurifier_AttrDef_Enum( - ['none', 'underline', 'overline', 'line-through'] - ); - - $this->info['text-decoration-style'] = new HTMLPurifier_AttrDef_Enum( - ['solid', 'double', 'dotted', 'dashed', 'wavy'] - ); - - $this->info['text-decoration-color'] = new HTMLPurifier_AttrDef_CSS_Color(); - - $this->info['text-decoration-thickness'] = new HTMLPurifier_AttrDef_CSS_Composite([ - new HTMLPurifier_AttrDef_CSS_Length(), - new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(['auto', 'from-font']) - ]); - $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily(); // this could use specialized code $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum( - [ + array( 'normal', 'bold', 'bolder', @@ -345,7 +324,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition '700', '800', '900' - ], + ), false ); @@ -361,21 +340,21 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config); $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum( - ['collapse', 'separate'] + array('collapse', 'separate') ); $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum( - ['top', 'bottom'] + array('top', 'bottom') ); $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum( - ['auto', 'fixed'] + array('auto', 'fixed') ); $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_Enum( - [ + array( 'baseline', 'sub', 'super', @@ -384,11 +363,11 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'middle', 'bottom', 'text-bottom' - ] + ) ), new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage() - ] + ) ); $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2); @@ -396,7 +375,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition // These CSS properties don't work on many browsers, but we live // in THE FUTURE! $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum( - ['nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line'] + array('nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line') ); if ($config->get('CSS.Proprietary')) { @@ -443,21 +422,21 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition // more CSS3 $this->info['page-break-after'] = $this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum( - [ + array( 'auto', 'always', 'avoid', 'left', 'right' - ] + ) ); - $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(['auto', 'avoid']); + $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid')); $border_radius = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Percentage(true), // disallow negative new HTMLPurifier_AttrDef_CSS_Length('0') // disallow negative - ]); + )); $this->info['border-top-left-radius'] = $this->info['border-top-right-radius'] = @@ -474,7 +453,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition protected function doSetupTricky($config) { $this->info['display'] = new HTMLPurifier_AttrDef_Enum( - [ + array( 'inline', 'block', 'list-item', @@ -493,12 +472,12 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition 'table-cell', 'table-caption', 'none' - ] + ) ); $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum( - ['visible', 'hidden', 'collapse'] + array('visible', 'hidden', 'collapse') ); - $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(['visible', 'hidden', 'auto', 'scroll']); + $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll')); $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); } @@ -508,23 +487,23 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition protected function doSetupTrusted($config) { $this->info['position'] = new HTMLPurifier_AttrDef_Enum( - ['static', 'relative', 'absolute', 'fixed'] + array('static', 'relative', 'absolute', 'fixed') ); $this->info['top'] = $this->info['left'] = $this->info['right'] = $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage(), - new HTMLPurifier_AttrDef_Enum(['auto']), - ] + new HTMLPurifier_AttrDef_Enum(array('auto')), + ) ); $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite( - [ + array( new HTMLPurifier_AttrDef_Integer(), - new HTMLPurifier_AttrDef_Enum(['auto']), - ] + new HTMLPurifier_AttrDef_Enum(array('auto')), + ) ); } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php index d92205b32..67c7e9535 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php @@ -190,9 +190,6 @@ class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef $current_tr_tbody = null; foreach($content as $node) { - if (!isset($node->name)) { - continue; - } switch ($node->name) { case 'tbody': $current_tr_tbody = null; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php index 256408e2f..797d26877 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php @@ -21,7 +21,7 @@ class HTMLPurifier_Config * HTML Purifier's version * @type string */ - public $version = '4.19.0'; + public $version = '4.15.0'; /** * Whether or not to automatically finalize @@ -898,11 +898,7 @@ class HTMLPurifier_Config break; } } - if ($no == E_USER_ERROR) { - throw new Exception($msg . $extra); - } else { - trigger_error($msg . $extra, $no); - } + trigger_error($msg . $extra, $no); } /** diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php index 42f660473..c3fe8cd4a 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php @@ -72,7 +72,7 @@ class HTMLPurifier_ConfigSchema $r = unserialize($contents); if (!$r) { $hash = sha1($contents); - throw new Exception("Unserialization of configuration schema failed, sha1 of file was $hash"); + trigger_error("Unserialization of configuration schema failed, sha1 of file was $hash", E_USER_ERROR); } return $r; } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php index 4902a56d9..127a39a67 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php @@ -66,7 +66,7 @@ class HTMLPurifier_ConfigSchema_Interchange_Directive public $version; /** - * ID of directive that supersedes this old directive. + * ID of directive that supercedes this old directive. * Null if not deprecated. * @type HTMLPurifier_ConfigSchema_Interchange_Id */ diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser index 34ea68371..a5426c736 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser @@ -1 +1 @@ -O:25:"HTMLPurifier_ConfigSchema":3:{s:8:"defaults";a:130:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";N;s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:23:"Core.AllowParseManyTags";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:148:{s:9:"aliceblue";s:7:"#F0F8FF";s:12:"antiquewhite";s:7:"#FAEBD7";s:4:"aqua";s:7:"#00FFFF";s:10:"aquamarine";s:7:"#7FFFD4";s:5:"azure";s:7:"#F0FFFF";s:5:"beige";s:7:"#F5F5DC";s:6:"bisque";s:7:"#FFE4C4";s:5:"black";s:7:"#000000";s:14:"blanchedalmond";s:7:"#FFEBCD";s:4:"blue";s:7:"#0000FF";s:10:"blueviolet";s:7:"#8A2BE2";s:5:"brown";s:7:"#A52A2A";s:9:"burlywood";s:7:"#DEB887";s:9:"cadetblue";s:7:"#5F9EA0";s:10:"chartreuse";s:7:"#7FFF00";s:9:"chocolate";s:7:"#D2691E";s:5:"coral";s:7:"#FF7F50";s:14:"cornflowerblue";s:7:"#6495ED";s:8:"cornsilk";s:7:"#FFF8DC";s:7:"crimson";s:7:"#DC143C";s:4:"cyan";s:7:"#00FFFF";s:8:"darkblue";s:7:"#00008B";s:8:"darkcyan";s:7:"#008B8B";s:13:"darkgoldenrod";s:7:"#B8860B";s:8:"darkgray";s:7:"#A9A9A9";s:8:"darkgrey";s:7:"#A9A9A9";s:9:"darkgreen";s:7:"#006400";s:9:"darkkhaki";s:7:"#BDB76B";s:11:"darkmagenta";s:7:"#8B008B";s:14:"darkolivegreen";s:7:"#556B2F";s:10:"darkorange";s:7:"#FF8C00";s:10:"darkorchid";s:7:"#9932CC";s:7:"darkred";s:7:"#8B0000";s:10:"darksalmon";s:7:"#E9967A";s:12:"darkseagreen";s:7:"#8FBC8F";s:13:"darkslateblue";s:7:"#483D8B";s:13:"darkslategray";s:7:"#2F4F4F";s:13:"darkslategrey";s:7:"#2F4F4F";s:13:"darkturquoise";s:7:"#00CED1";s:10:"darkviolet";s:7:"#9400D3";s:8:"deeppink";s:7:"#FF1493";s:11:"deepskyblue";s:7:"#00BFFF";s:7:"dimgray";s:7:"#696969";s:7:"dimgrey";s:7:"#696969";s:10:"dodgerblue";s:7:"#1E90FF";s:9:"firebrick";s:7:"#B22222";s:11:"floralwhite";s:7:"#FFFAF0";s:11:"forestgreen";s:7:"#228B22";s:7:"fuchsia";s:7:"#FF00FF";s:9:"gainsboro";s:7:"#DCDCDC";s:10:"ghostwhite";s:7:"#F8F8FF";s:4:"gold";s:7:"#FFD700";s:9:"goldenrod";s:7:"#DAA520";s:4:"gray";s:7:"#808080";s:4:"grey";s:7:"#808080";s:5:"green";s:7:"#008000";s:11:"greenyellow";s:7:"#ADFF2F";s:8:"honeydew";s:7:"#F0FFF0";s:7:"hotpink";s:7:"#FF69B4";s:9:"indianred";s:7:"#CD5C5C";s:6:"indigo";s:7:"#4B0082";s:5:"ivory";s:7:"#FFFFF0";s:5:"khaki";s:7:"#F0E68C";s:8:"lavender";s:7:"#E6E6FA";s:13:"lavenderblush";s:7:"#FFF0F5";s:9:"lawngreen";s:7:"#7CFC00";s:12:"lemonchiffon";s:7:"#FFFACD";s:9:"lightblue";s:7:"#ADD8E6";s:10:"lightcoral";s:7:"#F08080";s:9:"lightcyan";s:7:"#E0FFFF";s:20:"lightgoldenrodyellow";s:7:"#FAFAD2";s:9:"lightgray";s:7:"#D3D3D3";s:9:"lightgrey";s:7:"#D3D3D3";s:10:"lightgreen";s:7:"#90EE90";s:9:"lightpink";s:7:"#FFB6C1";s:11:"lightsalmon";s:7:"#FFA07A";s:13:"lightseagreen";s:7:"#20B2AA";s:12:"lightskyblue";s:7:"#87CEFA";s:14:"lightslategray";s:7:"#778899";s:14:"lightslategrey";s:7:"#778899";s:14:"lightsteelblue";s:7:"#B0C4DE";s:11:"lightyellow";s:7:"#FFFFE0";s:4:"lime";s:7:"#00FF00";s:9:"limegreen";s:7:"#32CD32";s:5:"linen";s:7:"#FAF0E6";s:7:"magenta";s:7:"#FF00FF";s:6:"maroon";s:7:"#800000";s:16:"mediumaquamarine";s:7:"#66CDAA";s:10:"mediumblue";s:7:"#0000CD";s:12:"mediumorchid";s:7:"#BA55D3";s:12:"mediumpurple";s:7:"#9370DB";s:14:"mediumseagreen";s:7:"#3CB371";s:15:"mediumslateblue";s:7:"#7B68EE";s:17:"mediumspringgreen";s:7:"#00FA9A";s:15:"mediumturquoise";s:7:"#48D1CC";s:15:"mediumvioletred";s:7:"#C71585";s:12:"midnightblue";s:7:"#191970";s:9:"mintcream";s:7:"#F5FFFA";s:9:"mistyrose";s:7:"#FFE4E1";s:8:"moccasin";s:7:"#FFE4B5";s:11:"navajowhite";s:7:"#FFDEAD";s:4:"navy";s:7:"#000080";s:7:"oldlace";s:7:"#FDF5E6";s:5:"olive";s:7:"#808000";s:9:"olivedrab";s:7:"#6B8E23";s:6:"orange";s:7:"#FFA500";s:9:"orangered";s:7:"#FF4500";s:6:"orchid";s:7:"#DA70D6";s:13:"palegoldenrod";s:7:"#EEE8AA";s:9:"palegreen";s:7:"#98FB98";s:13:"paleturquoise";s:7:"#AFEEEE";s:13:"palevioletred";s:7:"#DB7093";s:10:"papayawhip";s:7:"#FFEFD5";s:9:"peachpuff";s:7:"#FFDAB9";s:4:"peru";s:7:"#CD853F";s:4:"pink";s:7:"#FFC0CB";s:4:"plum";s:7:"#DDA0DD";s:10:"powderblue";s:7:"#B0E0E6";s:6:"purple";s:7:"#800080";s:13:"rebeccapurple";s:7:"#663399";s:3:"red";s:7:"#FF0000";s:9:"rosybrown";s:7:"#BC8F8F";s:9:"royalblue";s:7:"#4169E1";s:11:"saddlebrown";s:7:"#8B4513";s:6:"salmon";s:7:"#FA8072";s:10:"sandybrown";s:7:"#F4A460";s:8:"seagreen";s:7:"#2E8B57";s:8:"seashell";s:7:"#FFF5EE";s:6:"sienna";s:7:"#A0522D";s:6:"silver";s:7:"#C0C0C0";s:7:"skyblue";s:7:"#87CEEB";s:9:"slateblue";s:7:"#6A5ACD";s:9:"slategray";s:7:"#708090";s:9:"slategrey";s:7:"#708090";s:4:"snow";s:7:"#FFFAFA";s:11:"springgreen";s:7:"#00FF7F";s:9:"steelblue";s:7:"#4682B4";s:3:"tan";s:7:"#D2B48C";s:4:"teal";s:7:"#008080";s:7:"thistle";s:7:"#D8BFD8";s:6:"tomato";s:7:"#FF6347";s:9:"turquoise";s:7:"#40E0D0";s:6:"violet";s:7:"#EE82EE";s:5:"wheat";s:7:"#F5DEB3";s:5:"white";s:7:"#FFFFFF";s:10:"whitesmoke";s:7:"#F5F5F5";s:6:"yellow";s:7:"#FFFF00";s:11:"yellowgreen";s:7:"#9ACD32";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:17:"Core.RemoveBlanks";b:0;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:10:"HTML.Forms";b:0;s:17:"HTML.MaxImgLength";N;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:18:"URI.AllowedSymbols";s:11:"!$&'()*+,;=";s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:19:"URI.SafeIframeHosts";N;s:20:"URI.SafeIframeRegexp";N;}s:12:"defaultPlist";O:25:"HTMLPurifier_PropertyList":3:{s:7:"*data";a:130:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";N;s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:23:"Core.AllowParseManyTags";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:148:{s:9:"aliceblue";s:7:"#F0F8FF";s:12:"antiquewhite";s:7:"#FAEBD7";s:4:"aqua";s:7:"#00FFFF";s:10:"aquamarine";s:7:"#7FFFD4";s:5:"azure";s:7:"#F0FFFF";s:5:"beige";s:7:"#F5F5DC";s:6:"bisque";s:7:"#FFE4C4";s:5:"black";s:7:"#000000";s:14:"blanchedalmond";s:7:"#FFEBCD";s:4:"blue";s:7:"#0000FF";s:10:"blueviolet";s:7:"#8A2BE2";s:5:"brown";s:7:"#A52A2A";s:9:"burlywood";s:7:"#DEB887";s:9:"cadetblue";s:7:"#5F9EA0";s:10:"chartreuse";s:7:"#7FFF00";s:9:"chocolate";s:7:"#D2691E";s:5:"coral";s:7:"#FF7F50";s:14:"cornflowerblue";s:7:"#6495ED";s:8:"cornsilk";s:7:"#FFF8DC";s:7:"crimson";s:7:"#DC143C";s:4:"cyan";s:7:"#00FFFF";s:8:"darkblue";s:7:"#00008B";s:8:"darkcyan";s:7:"#008B8B";s:13:"darkgoldenrod";s:7:"#B8860B";s:8:"darkgray";s:7:"#A9A9A9";s:8:"darkgrey";s:7:"#A9A9A9";s:9:"darkgreen";s:7:"#006400";s:9:"darkkhaki";s:7:"#BDB76B";s:11:"darkmagenta";s:7:"#8B008B";s:14:"darkolivegreen";s:7:"#556B2F";s:10:"darkorange";s:7:"#FF8C00";s:10:"darkorchid";s:7:"#9932CC";s:7:"darkred";s:7:"#8B0000";s:10:"darksalmon";s:7:"#E9967A";s:12:"darkseagreen";s:7:"#8FBC8F";s:13:"darkslateblue";s:7:"#483D8B";s:13:"darkslategray";s:7:"#2F4F4F";s:13:"darkslategrey";s:7:"#2F4F4F";s:13:"darkturquoise";s:7:"#00CED1";s:10:"darkviolet";s:7:"#9400D3";s:8:"deeppink";s:7:"#FF1493";s:11:"deepskyblue";s:7:"#00BFFF";s:7:"dimgray";s:7:"#696969";s:7:"dimgrey";s:7:"#696969";s:10:"dodgerblue";s:7:"#1E90FF";s:9:"firebrick";s:7:"#B22222";s:11:"floralwhite";s:7:"#FFFAF0";s:11:"forestgreen";s:7:"#228B22";s:7:"fuchsia";s:7:"#FF00FF";s:9:"gainsboro";s:7:"#DCDCDC";s:10:"ghostwhite";s:7:"#F8F8FF";s:4:"gold";s:7:"#FFD700";s:9:"goldenrod";s:7:"#DAA520";s:4:"gray";s:7:"#808080";s:4:"grey";s:7:"#808080";s:5:"green";s:7:"#008000";s:11:"greenyellow";s:7:"#ADFF2F";s:8:"honeydew";s:7:"#F0FFF0";s:7:"hotpink";s:7:"#FF69B4";s:9:"indianred";s:7:"#CD5C5C";s:6:"indigo";s:7:"#4B0082";s:5:"ivory";s:7:"#FFFFF0";s:5:"khaki";s:7:"#F0E68C";s:8:"lavender";s:7:"#E6E6FA";s:13:"lavenderblush";s:7:"#FFF0F5";s:9:"lawngreen";s:7:"#7CFC00";s:12:"lemonchiffon";s:7:"#FFFACD";s:9:"lightblue";s:7:"#ADD8E6";s:10:"lightcoral";s:7:"#F08080";s:9:"lightcyan";s:7:"#E0FFFF";s:20:"lightgoldenrodyellow";s:7:"#FAFAD2";s:9:"lightgray";s:7:"#D3D3D3";s:9:"lightgrey";s:7:"#D3D3D3";s:10:"lightgreen";s:7:"#90EE90";s:9:"lightpink";s:7:"#FFB6C1";s:11:"lightsalmon";s:7:"#FFA07A";s:13:"lightseagreen";s:7:"#20B2AA";s:12:"lightskyblue";s:7:"#87CEFA";s:14:"lightslategray";s:7:"#778899";s:14:"lightslategrey";s:7:"#778899";s:14:"lightsteelblue";s:7:"#B0C4DE";s:11:"lightyellow";s:7:"#FFFFE0";s:4:"lime";s:7:"#00FF00";s:9:"limegreen";s:7:"#32CD32";s:5:"linen";s:7:"#FAF0E6";s:7:"magenta";s:7:"#FF00FF";s:6:"maroon";s:7:"#800000";s:16:"mediumaquamarine";s:7:"#66CDAA";s:10:"mediumblue";s:7:"#0000CD";s:12:"mediumorchid";s:7:"#BA55D3";s:12:"mediumpurple";s:7:"#9370DB";s:14:"mediumseagreen";s:7:"#3CB371";s:15:"mediumslateblue";s:7:"#7B68EE";s:17:"mediumspringgreen";s:7:"#00FA9A";s:15:"mediumturquoise";s:7:"#48D1CC";s:15:"mediumvioletred";s:7:"#C71585";s:12:"midnightblue";s:7:"#191970";s:9:"mintcream";s:7:"#F5FFFA";s:9:"mistyrose";s:7:"#FFE4E1";s:8:"moccasin";s:7:"#FFE4B5";s:11:"navajowhite";s:7:"#FFDEAD";s:4:"navy";s:7:"#000080";s:7:"oldlace";s:7:"#FDF5E6";s:5:"olive";s:7:"#808000";s:9:"olivedrab";s:7:"#6B8E23";s:6:"orange";s:7:"#FFA500";s:9:"orangered";s:7:"#FF4500";s:6:"orchid";s:7:"#DA70D6";s:13:"palegoldenrod";s:7:"#EEE8AA";s:9:"palegreen";s:7:"#98FB98";s:13:"paleturquoise";s:7:"#AFEEEE";s:13:"palevioletred";s:7:"#DB7093";s:10:"papayawhip";s:7:"#FFEFD5";s:9:"peachpuff";s:7:"#FFDAB9";s:4:"peru";s:7:"#CD853F";s:4:"pink";s:7:"#FFC0CB";s:4:"plum";s:7:"#DDA0DD";s:10:"powderblue";s:7:"#B0E0E6";s:6:"purple";s:7:"#800080";s:13:"rebeccapurple";s:7:"#663399";s:3:"red";s:7:"#FF0000";s:9:"rosybrown";s:7:"#BC8F8F";s:9:"royalblue";s:7:"#4169E1";s:11:"saddlebrown";s:7:"#8B4513";s:6:"salmon";s:7:"#FA8072";s:10:"sandybrown";s:7:"#F4A460";s:8:"seagreen";s:7:"#2E8B57";s:8:"seashell";s:7:"#FFF5EE";s:6:"sienna";s:7:"#A0522D";s:6:"silver";s:7:"#C0C0C0";s:7:"skyblue";s:7:"#87CEEB";s:9:"slateblue";s:7:"#6A5ACD";s:9:"slategray";s:7:"#708090";s:9:"slategrey";s:7:"#708090";s:4:"snow";s:7:"#FFFAFA";s:11:"springgreen";s:7:"#00FF7F";s:9:"steelblue";s:7:"#4682B4";s:3:"tan";s:7:"#D2B48C";s:4:"teal";s:7:"#008080";s:7:"thistle";s:7:"#D8BFD8";s:6:"tomato";s:7:"#FF6347";s:9:"turquoise";s:7:"#40E0D0";s:6:"violet";s:7:"#EE82EE";s:5:"wheat";s:7:"#F5DEB3";s:5:"white";s:7:"#FFFFFF";s:10:"whitesmoke";s:7:"#F5F5F5";s:6:"yellow";s:7:"#FFFF00";s:11:"yellowgreen";s:7:"#9ACD32";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:17:"Core.RemoveBlanks";b:0;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:10:"HTML.Forms";b:0;s:17:"HTML.MaxImgLength";N;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:18:"URI.AllowedSymbols";s:11:"!$&'()*+,;=";s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:19:"URI.SafeIframeHosts";N;s:20:"URI.SafeIframeRegexp";N;}s:9:"*parent";N;s:8:"*cache";N;}s:4:"info";a:143:{s:19:"Attr.AllowedClasses";i:-8;s:24:"Attr.AllowedFrameTargets";i:8;s:15:"Attr.AllowedRel";i:8;s:15:"Attr.AllowedRev";i:8;s:18:"Attr.ClassUseCDATA";i:-7;s:20:"Attr.DefaultImageAlt";i:-1;s:24:"Attr.DefaultInvalidImage";i:1;s:27:"Attr.DefaultInvalidImageAlt";i:1;s:19:"Attr.DefaultTextDir";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:2:{s:3:"ltr";b:1;s:3:"rtl";b:1;}}s:13:"Attr.EnableID";i:7;s:17:"HTML.EnableAttrID";O:8:"stdClass":2:{s:3:"key";s:13:"Attr.EnableID";s:7:"isAlias";b:1;}s:21:"Attr.ForbiddenClasses";i:8;s:13:"Attr.ID.HTML5";i:-7;s:16:"Attr.IDBlacklist";i:9;s:22:"Attr.IDBlacklistRegexp";i:-1;s:13:"Attr.IDPrefix";i:1;s:18:"Attr.IDPrefixLocal";i:1;s:24:"AutoFormat.AutoParagraph";i:7;s:17:"AutoFormat.Custom";i:9;s:25:"AutoFormat.DisplayLinkURI";i:7;s:18:"AutoFormat.Linkify";i:7;s:33:"AutoFormat.PurifierLinkify.DocURL";i:1;s:37:"AutoFormatParam.PurifierLinkifyDocURL";O:8:"stdClass":2:{s:3:"key";s:33:"AutoFormat.PurifierLinkify.DocURL";s:7:"isAlias";b:1;}s:26:"AutoFormat.PurifierLinkify";i:7;s:32:"AutoFormat.RemoveEmpty.Predicate";i:10;s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";i:8;s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";i:7;s:22:"AutoFormat.RemoveEmpty";i:7;s:39:"AutoFormat.RemoveSpansWithoutAttributes";i:7;s:19:"CSS.AllowDuplicates";i:7;s:18:"CSS.AllowImportant";i:7;s:15:"CSS.AllowTricky";i:7;s:16:"CSS.AllowedFonts";i:-8;s:21:"CSS.AllowedProperties";i:-8;s:17:"CSS.DefinitionRev";i:5;s:23:"CSS.ForbiddenProperties";i:8;s:16:"CSS.MaxImgLength";i:-1;s:15:"CSS.Proprietary";i:7;s:11:"CSS.Trusted";i:7;s:20:"Cache.DefinitionImpl";i:-1;s:20:"Core.DefinitionCache";O:8:"stdClass":2:{s:3:"key";s:20:"Cache.DefinitionImpl";s:7:"isAlias";b:1;}s:20:"Cache.SerializerPath";i:-1;s:27:"Cache.SerializerPermissions";i:-5;s:22:"Core.AggressivelyFixLt";i:7;s:29:"Core.AggressivelyRemoveScript";i:7;s:28:"Core.AllowHostnameUnderscore";i:7;s:23:"Core.AllowParseManyTags";i:7;s:18:"Core.CollectErrors";i:7;s:18:"Core.ColorKeywords";i:10;s:30:"Core.ConvertDocumentToFragment";i:7;s:24:"Core.AcceptFullDocuments";O:8:"stdClass":2:{s:3:"key";s:30:"Core.ConvertDocumentToFragment";s:7:"isAlias";b:1;}s:36:"Core.DirectLexLineNumberSyncInterval";i:5;s:20:"Core.DisableExcludes";i:7;s:15:"Core.EnableIDNA";i:7;s:13:"Core.Encoding";i:2;s:26:"Core.EscapeInvalidChildren";i:7;s:22:"Core.EscapeInvalidTags";i:7;s:29:"Core.EscapeNonASCIICharacters";i:7;s:19:"Core.HiddenElements";i:8;s:13:"Core.Language";i:1;s:24:"Core.LegacyEntityDecoder";i:7;s:14:"Core.LexerImpl";i:-11;s:24:"Core.MaintainLineNumbers";i:-7;s:22:"Core.NormalizeNewlines";i:7;s:17:"Core.RemoveBlanks";i:7;s:21:"Core.RemoveInvalidImg";i:7;s:33:"Core.RemoveProcessingInstructions";i:7;s:25:"Core.RemoveScriptContents";i:-7;s:13:"Filter.Custom";i:9;s:34:"Filter.ExtractStyleBlocks.Escaping";i:7;s:33:"Filter.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:38:"FilterParam.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:31:"Filter.ExtractStyleBlocks.Scope";i:-1;s:30:"Filter.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:35:"FilterParam.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:34:"Filter.ExtractStyleBlocks.TidyImpl";i:-11;s:38:"FilterParam.ExtractStyleBlocksTidyImpl";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.TidyImpl";s:7:"isAlias";b:1;}s:25:"Filter.ExtractStyleBlocks";i:7;s:14:"Filter.YouTube";i:7;s:12:"HTML.Allowed";i:-4;s:22:"HTML.AllowedAttributes";i:-8;s:20:"HTML.AllowedComments";i:8;s:26:"HTML.AllowedCommentsRegexp";i:-1;s:20:"HTML.AllowedElements";i:-8;s:19:"HTML.AllowedModules";i:-8;s:23:"HTML.Attr.Name.UseCDATA";i:7;s:17:"HTML.BlockWrapper";i:1;s:16:"HTML.CoreModules";i:8;s:18:"HTML.CustomDoctype";i:-1;s:17:"HTML.DefinitionID";i:-1;s:18:"HTML.DefinitionRev";i:5;s:12:"HTML.Doctype";O:8:"stdClass":3:{s:4:"type";i:1;s:10:"allow_null";b:1;s:7:"allowed";a:5:{s:22:"HTML 4.01 Transitional";b:1;s:16:"HTML 4.01 Strict";b:1;s:22:"XHTML 1.0 Transitional";b:1;s:16:"XHTML 1.0 Strict";b:1;s:9:"XHTML 1.1";b:1;}}s:25:"HTML.FlashAllowFullScreen";i:7;s:24:"HTML.ForbiddenAttributes";i:8;s:22:"HTML.ForbiddenElements";i:8;s:10:"HTML.Forms";i:7;s:17:"HTML.MaxImgLength";i:-5;s:13:"HTML.Nofollow";i:7;s:11:"HTML.Parent";i:1;s:16:"HTML.Proprietary";i:7;s:14:"HTML.SafeEmbed";i:7;s:15:"HTML.SafeIframe";i:7;s:15:"HTML.SafeObject";i:7;s:18:"HTML.SafeScripting";i:8;s:11:"HTML.Strict";i:7;s:16:"HTML.TargetBlank";i:7;s:19:"HTML.TargetNoopener";i:7;s:21:"HTML.TargetNoreferrer";i:7;s:12:"HTML.TidyAdd";i:8;s:14:"HTML.TidyLevel";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:4:{s:4:"none";b:1;s:5:"light";b:1;s:6:"medium";b:1;s:5:"heavy";b:1;}}s:15:"HTML.TidyRemove";i:8;s:12:"HTML.Trusted";i:7;s:10:"HTML.XHTML";i:7;s:10:"Core.XHTML";O:8:"stdClass":2:{s:3:"key";s:10:"HTML.XHTML";s:7:"isAlias";b:1;}s:28:"Output.CommentScriptContents";i:7;s:26:"Core.CommentScriptContents";O:8:"stdClass":2:{s:3:"key";s:28:"Output.CommentScriptContents";s:7:"isAlias";b:1;}s:19:"Output.FixInnerHTML";i:7;s:18:"Output.FlashCompat";i:7;s:14:"Output.Newline";i:-1;s:15:"Output.SortAttr";i:7;s:17:"Output.TidyFormat";i:7;s:15:"Core.TidyFormat";O:8:"stdClass":2:{s:3:"key";s:17:"Output.TidyFormat";s:7:"isAlias";b:1;}s:17:"Test.ForceNoIconv";i:7;s:18:"URI.AllowedSchemes";i:8;s:18:"URI.AllowedSymbols";i:-1;s:8:"URI.Base";i:-1;s:17:"URI.DefaultScheme";i:-1;s:16:"URI.DefinitionID";i:-1;s:17:"URI.DefinitionRev";i:5;s:11:"URI.Disable";i:7;s:15:"Attr.DisableURI";O:8:"stdClass":2:{s:3:"key";s:11:"URI.Disable";s:7:"isAlias";b:1;}s:19:"URI.DisableExternal";i:7;s:28:"URI.DisableExternalResources";i:7;s:20:"URI.DisableResources";i:7;s:8:"URI.Host";i:-1;s:17:"URI.HostBlacklist";i:9;s:16:"URI.MakeAbsolute";i:7;s:9:"URI.Munge";i:-1;s:18:"URI.MungeResources";i:7;s:18:"URI.MungeSecretKey";i:-1;s:26:"URI.OverrideAllowedSchemes";i:7;s:19:"URI.SafeIframeHosts";i:-8;s:20:"URI.SafeIframeRegexp";i:-1;}} \ No newline at end of file +O:25:"HTMLPurifier_ConfigSchema":3:{s:8:"defaults";a:127:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:23:"Core.AllowParseManyTags";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:148:{s:9:"aliceblue";s:7:"#F0F8FF";s:12:"antiquewhite";s:7:"#FAEBD7";s:4:"aqua";s:7:"#00FFFF";s:10:"aquamarine";s:7:"#7FFFD4";s:5:"azure";s:7:"#F0FFFF";s:5:"beige";s:7:"#F5F5DC";s:6:"bisque";s:7:"#FFE4C4";s:5:"black";s:7:"#000000";s:14:"blanchedalmond";s:7:"#FFEBCD";s:4:"blue";s:7:"#0000FF";s:10:"blueviolet";s:7:"#8A2BE2";s:5:"brown";s:7:"#A52A2A";s:9:"burlywood";s:7:"#DEB887";s:9:"cadetblue";s:7:"#5F9EA0";s:10:"chartreuse";s:7:"#7FFF00";s:9:"chocolate";s:7:"#D2691E";s:5:"coral";s:7:"#FF7F50";s:14:"cornflowerblue";s:7:"#6495ED";s:8:"cornsilk";s:7:"#FFF8DC";s:7:"crimson";s:7:"#DC143C";s:4:"cyan";s:7:"#00FFFF";s:8:"darkblue";s:7:"#00008B";s:8:"darkcyan";s:7:"#008B8B";s:13:"darkgoldenrod";s:7:"#B8860B";s:8:"darkgray";s:7:"#A9A9A9";s:8:"darkgrey";s:7:"#A9A9A9";s:9:"darkgreen";s:7:"#006400";s:9:"darkkhaki";s:7:"#BDB76B";s:11:"darkmagenta";s:7:"#8B008B";s:14:"darkolivegreen";s:7:"#556B2F";s:10:"darkorange";s:7:"#FF8C00";s:10:"darkorchid";s:7:"#9932CC";s:7:"darkred";s:7:"#8B0000";s:10:"darksalmon";s:7:"#E9967A";s:12:"darkseagreen";s:7:"#8FBC8F";s:13:"darkslateblue";s:7:"#483D8B";s:13:"darkslategray";s:7:"#2F4F4F";s:13:"darkslategrey";s:7:"#2F4F4F";s:13:"darkturquoise";s:7:"#00CED1";s:10:"darkviolet";s:7:"#9400D3";s:8:"deeppink";s:7:"#FF1493";s:11:"deepskyblue";s:7:"#00BFFF";s:7:"dimgray";s:7:"#696969";s:7:"dimgrey";s:7:"#696969";s:10:"dodgerblue";s:7:"#1E90FF";s:9:"firebrick";s:7:"#B22222";s:11:"floralwhite";s:7:"#FFFAF0";s:11:"forestgreen";s:7:"#228B22";s:7:"fuchsia";s:7:"#FF00FF";s:9:"gainsboro";s:7:"#DCDCDC";s:10:"ghostwhite";s:7:"#F8F8FF";s:4:"gold";s:7:"#FFD700";s:9:"goldenrod";s:7:"#DAA520";s:4:"gray";s:7:"#808080";s:4:"grey";s:7:"#808080";s:5:"green";s:7:"#008000";s:11:"greenyellow";s:7:"#ADFF2F";s:8:"honeydew";s:7:"#F0FFF0";s:7:"hotpink";s:7:"#FF69B4";s:9:"indianred";s:7:"#CD5C5C";s:6:"indigo";s:7:"#4B0082";s:5:"ivory";s:7:"#FFFFF0";s:5:"khaki";s:7:"#F0E68C";s:8:"lavender";s:7:"#E6E6FA";s:13:"lavenderblush";s:7:"#FFF0F5";s:9:"lawngreen";s:7:"#7CFC00";s:12:"lemonchiffon";s:7:"#FFFACD";s:9:"lightblue";s:7:"#ADD8E6";s:10:"lightcoral";s:7:"#F08080";s:9:"lightcyan";s:7:"#E0FFFF";s:20:"lightgoldenrodyellow";s:7:"#FAFAD2";s:9:"lightgray";s:7:"#D3D3D3";s:9:"lightgrey";s:7:"#D3D3D3";s:10:"lightgreen";s:7:"#90EE90";s:9:"lightpink";s:7:"#FFB6C1";s:11:"lightsalmon";s:7:"#FFA07A";s:13:"lightseagreen";s:7:"#20B2AA";s:12:"lightskyblue";s:7:"#87CEFA";s:14:"lightslategray";s:7:"#778899";s:14:"lightslategrey";s:7:"#778899";s:14:"lightsteelblue";s:7:"#B0C4DE";s:11:"lightyellow";s:7:"#FFFFE0";s:4:"lime";s:7:"#00FF00";s:9:"limegreen";s:7:"#32CD32";s:5:"linen";s:7:"#FAF0E6";s:7:"magenta";s:7:"#FF00FF";s:6:"maroon";s:7:"#800000";s:16:"mediumaquamarine";s:7:"#66CDAA";s:10:"mediumblue";s:7:"#0000CD";s:12:"mediumorchid";s:7:"#BA55D3";s:12:"mediumpurple";s:7:"#9370DB";s:14:"mediumseagreen";s:7:"#3CB371";s:15:"mediumslateblue";s:7:"#7B68EE";s:17:"mediumspringgreen";s:7:"#00FA9A";s:15:"mediumturquoise";s:7:"#48D1CC";s:15:"mediumvioletred";s:7:"#C71585";s:12:"midnightblue";s:7:"#191970";s:9:"mintcream";s:7:"#F5FFFA";s:9:"mistyrose";s:7:"#FFE4E1";s:8:"moccasin";s:7:"#FFE4B5";s:11:"navajowhite";s:7:"#FFDEAD";s:4:"navy";s:7:"#000080";s:7:"oldlace";s:7:"#FDF5E6";s:5:"olive";s:7:"#808000";s:9:"olivedrab";s:7:"#6B8E23";s:6:"orange";s:7:"#FFA500";s:9:"orangered";s:7:"#FF4500";s:6:"orchid";s:7:"#DA70D6";s:13:"palegoldenrod";s:7:"#EEE8AA";s:9:"palegreen";s:7:"#98FB98";s:13:"paleturquoise";s:7:"#AFEEEE";s:13:"palevioletred";s:7:"#DB7093";s:10:"papayawhip";s:7:"#FFEFD5";s:9:"peachpuff";s:7:"#FFDAB9";s:4:"peru";s:7:"#CD853F";s:4:"pink";s:7:"#FFC0CB";s:4:"plum";s:7:"#DDA0DD";s:10:"powderblue";s:7:"#B0E0E6";s:6:"purple";s:7:"#800080";s:13:"rebeccapurple";s:7:"#663399";s:3:"red";s:7:"#FF0000";s:9:"rosybrown";s:7:"#BC8F8F";s:9:"royalblue";s:7:"#4169E1";s:11:"saddlebrown";s:7:"#8B4513";s:6:"salmon";s:7:"#FA8072";s:10:"sandybrown";s:7:"#F4A460";s:8:"seagreen";s:7:"#2E8B57";s:8:"seashell";s:7:"#FFF5EE";s:6:"sienna";s:7:"#A0522D";s:6:"silver";s:7:"#C0C0C0";s:7:"skyblue";s:7:"#87CEEB";s:9:"slateblue";s:7:"#6A5ACD";s:9:"slategray";s:7:"#708090";s:9:"slategrey";s:7:"#708090";s:4:"snow";s:7:"#FFFAFA";s:11:"springgreen";s:7:"#00FF7F";s:9:"steelblue";s:7:"#4682B4";s:3:"tan";s:7:"#D2B48C";s:4:"teal";s:7:"#008080";s:7:"thistle";s:7:"#D8BFD8";s:6:"tomato";s:7:"#FF6347";s:9:"turquoise";s:7:"#40E0D0";s:6:"violet";s:7:"#EE82EE";s:5:"wheat";s:7:"#F5DEB3";s:5:"white";s:7:"#FFFFFF";s:10:"whitesmoke";s:7:"#F5F5F5";s:6:"yellow";s:7:"#FFFF00";s:11:"yellowgreen";s:7:"#9ACD32";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:10:"HTML.Forms";b:0;s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:12:"defaultPlist";O:25:"HTMLPurifier_PropertyList":3:{s:7:"*data";a:127:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:23:"Core.AllowParseManyTags";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:148:{s:9:"aliceblue";s:7:"#F0F8FF";s:12:"antiquewhite";s:7:"#FAEBD7";s:4:"aqua";s:7:"#00FFFF";s:10:"aquamarine";s:7:"#7FFFD4";s:5:"azure";s:7:"#F0FFFF";s:5:"beige";s:7:"#F5F5DC";s:6:"bisque";s:7:"#FFE4C4";s:5:"black";s:7:"#000000";s:14:"blanchedalmond";s:7:"#FFEBCD";s:4:"blue";s:7:"#0000FF";s:10:"blueviolet";s:7:"#8A2BE2";s:5:"brown";s:7:"#A52A2A";s:9:"burlywood";s:7:"#DEB887";s:9:"cadetblue";s:7:"#5F9EA0";s:10:"chartreuse";s:7:"#7FFF00";s:9:"chocolate";s:7:"#D2691E";s:5:"coral";s:7:"#FF7F50";s:14:"cornflowerblue";s:7:"#6495ED";s:8:"cornsilk";s:7:"#FFF8DC";s:7:"crimson";s:7:"#DC143C";s:4:"cyan";s:7:"#00FFFF";s:8:"darkblue";s:7:"#00008B";s:8:"darkcyan";s:7:"#008B8B";s:13:"darkgoldenrod";s:7:"#B8860B";s:8:"darkgray";s:7:"#A9A9A9";s:8:"darkgrey";s:7:"#A9A9A9";s:9:"darkgreen";s:7:"#006400";s:9:"darkkhaki";s:7:"#BDB76B";s:11:"darkmagenta";s:7:"#8B008B";s:14:"darkolivegreen";s:7:"#556B2F";s:10:"darkorange";s:7:"#FF8C00";s:10:"darkorchid";s:7:"#9932CC";s:7:"darkred";s:7:"#8B0000";s:10:"darksalmon";s:7:"#E9967A";s:12:"darkseagreen";s:7:"#8FBC8F";s:13:"darkslateblue";s:7:"#483D8B";s:13:"darkslategray";s:7:"#2F4F4F";s:13:"darkslategrey";s:7:"#2F4F4F";s:13:"darkturquoise";s:7:"#00CED1";s:10:"darkviolet";s:7:"#9400D3";s:8:"deeppink";s:7:"#FF1493";s:11:"deepskyblue";s:7:"#00BFFF";s:7:"dimgray";s:7:"#696969";s:7:"dimgrey";s:7:"#696969";s:10:"dodgerblue";s:7:"#1E90FF";s:9:"firebrick";s:7:"#B22222";s:11:"floralwhite";s:7:"#FFFAF0";s:11:"forestgreen";s:7:"#228B22";s:7:"fuchsia";s:7:"#FF00FF";s:9:"gainsboro";s:7:"#DCDCDC";s:10:"ghostwhite";s:7:"#F8F8FF";s:4:"gold";s:7:"#FFD700";s:9:"goldenrod";s:7:"#DAA520";s:4:"gray";s:7:"#808080";s:4:"grey";s:7:"#808080";s:5:"green";s:7:"#008000";s:11:"greenyellow";s:7:"#ADFF2F";s:8:"honeydew";s:7:"#F0FFF0";s:7:"hotpink";s:7:"#FF69B4";s:9:"indianred";s:7:"#CD5C5C";s:6:"indigo";s:7:"#4B0082";s:5:"ivory";s:7:"#FFFFF0";s:5:"khaki";s:7:"#F0E68C";s:8:"lavender";s:7:"#E6E6FA";s:13:"lavenderblush";s:7:"#FFF0F5";s:9:"lawngreen";s:7:"#7CFC00";s:12:"lemonchiffon";s:7:"#FFFACD";s:9:"lightblue";s:7:"#ADD8E6";s:10:"lightcoral";s:7:"#F08080";s:9:"lightcyan";s:7:"#E0FFFF";s:20:"lightgoldenrodyellow";s:7:"#FAFAD2";s:9:"lightgray";s:7:"#D3D3D3";s:9:"lightgrey";s:7:"#D3D3D3";s:10:"lightgreen";s:7:"#90EE90";s:9:"lightpink";s:7:"#FFB6C1";s:11:"lightsalmon";s:7:"#FFA07A";s:13:"lightseagreen";s:7:"#20B2AA";s:12:"lightskyblue";s:7:"#87CEFA";s:14:"lightslategray";s:7:"#778899";s:14:"lightslategrey";s:7:"#778899";s:14:"lightsteelblue";s:7:"#B0C4DE";s:11:"lightyellow";s:7:"#FFFFE0";s:4:"lime";s:7:"#00FF00";s:9:"limegreen";s:7:"#32CD32";s:5:"linen";s:7:"#FAF0E6";s:7:"magenta";s:7:"#FF00FF";s:6:"maroon";s:7:"#800000";s:16:"mediumaquamarine";s:7:"#66CDAA";s:10:"mediumblue";s:7:"#0000CD";s:12:"mediumorchid";s:7:"#BA55D3";s:12:"mediumpurple";s:7:"#9370DB";s:14:"mediumseagreen";s:7:"#3CB371";s:15:"mediumslateblue";s:7:"#7B68EE";s:17:"mediumspringgreen";s:7:"#00FA9A";s:15:"mediumturquoise";s:7:"#48D1CC";s:15:"mediumvioletred";s:7:"#C71585";s:12:"midnightblue";s:7:"#191970";s:9:"mintcream";s:7:"#F5FFFA";s:9:"mistyrose";s:7:"#FFE4E1";s:8:"moccasin";s:7:"#FFE4B5";s:11:"navajowhite";s:7:"#FFDEAD";s:4:"navy";s:7:"#000080";s:7:"oldlace";s:7:"#FDF5E6";s:5:"olive";s:7:"#808000";s:9:"olivedrab";s:7:"#6B8E23";s:6:"orange";s:7:"#FFA500";s:9:"orangered";s:7:"#FF4500";s:6:"orchid";s:7:"#DA70D6";s:13:"palegoldenrod";s:7:"#EEE8AA";s:9:"palegreen";s:7:"#98FB98";s:13:"paleturquoise";s:7:"#AFEEEE";s:13:"palevioletred";s:7:"#DB7093";s:10:"papayawhip";s:7:"#FFEFD5";s:9:"peachpuff";s:7:"#FFDAB9";s:4:"peru";s:7:"#CD853F";s:4:"pink";s:7:"#FFC0CB";s:4:"plum";s:7:"#DDA0DD";s:10:"powderblue";s:7:"#B0E0E6";s:6:"purple";s:7:"#800080";s:13:"rebeccapurple";s:7:"#663399";s:3:"red";s:7:"#FF0000";s:9:"rosybrown";s:7:"#BC8F8F";s:9:"royalblue";s:7:"#4169E1";s:11:"saddlebrown";s:7:"#8B4513";s:6:"salmon";s:7:"#FA8072";s:10:"sandybrown";s:7:"#F4A460";s:8:"seagreen";s:7:"#2E8B57";s:8:"seashell";s:7:"#FFF5EE";s:6:"sienna";s:7:"#A0522D";s:6:"silver";s:7:"#C0C0C0";s:7:"skyblue";s:7:"#87CEEB";s:9:"slateblue";s:7:"#6A5ACD";s:9:"slategray";s:7:"#708090";s:9:"slategrey";s:7:"#708090";s:4:"snow";s:7:"#FFFAFA";s:11:"springgreen";s:7:"#00FF7F";s:9:"steelblue";s:7:"#4682B4";s:3:"tan";s:7:"#D2B48C";s:4:"teal";s:7:"#008080";s:7:"thistle";s:7:"#D8BFD8";s:6:"tomato";s:7:"#FF6347";s:9:"turquoise";s:7:"#40E0D0";s:6:"violet";s:7:"#EE82EE";s:5:"wheat";s:7:"#F5DEB3";s:5:"white";s:7:"#FFFFFF";s:10:"whitesmoke";s:7:"#F5F5F5";s:6:"yellow";s:7:"#FFFF00";s:11:"yellowgreen";s:7:"#9ACD32";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:10:"HTML.Forms";b:0;s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:9:"*parent";N;s:8:"*cache";N;}s:4:"info";a:140:{s:19:"Attr.AllowedClasses";i:-8;s:24:"Attr.AllowedFrameTargets";i:8;s:15:"Attr.AllowedRel";i:8;s:15:"Attr.AllowedRev";i:8;s:18:"Attr.ClassUseCDATA";i:-7;s:20:"Attr.DefaultImageAlt";i:-1;s:24:"Attr.DefaultInvalidImage";i:1;s:27:"Attr.DefaultInvalidImageAlt";i:1;s:19:"Attr.DefaultTextDir";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:2:{s:3:"ltr";b:1;s:3:"rtl";b:1;}}s:13:"Attr.EnableID";i:7;s:17:"HTML.EnableAttrID";O:8:"stdClass":2:{s:3:"key";s:13:"Attr.EnableID";s:7:"isAlias";b:1;}s:21:"Attr.ForbiddenClasses";i:8;s:13:"Attr.ID.HTML5";i:-7;s:16:"Attr.IDBlacklist";i:9;s:22:"Attr.IDBlacklistRegexp";i:-1;s:13:"Attr.IDPrefix";i:1;s:18:"Attr.IDPrefixLocal";i:1;s:24:"AutoFormat.AutoParagraph";i:7;s:17:"AutoFormat.Custom";i:9;s:25:"AutoFormat.DisplayLinkURI";i:7;s:18:"AutoFormat.Linkify";i:7;s:33:"AutoFormat.PurifierLinkify.DocURL";i:1;s:37:"AutoFormatParam.PurifierLinkifyDocURL";O:8:"stdClass":2:{s:3:"key";s:33:"AutoFormat.PurifierLinkify.DocURL";s:7:"isAlias";b:1;}s:26:"AutoFormat.PurifierLinkify";i:7;s:32:"AutoFormat.RemoveEmpty.Predicate";i:10;s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";i:8;s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";i:7;s:22:"AutoFormat.RemoveEmpty";i:7;s:39:"AutoFormat.RemoveSpansWithoutAttributes";i:7;s:19:"CSS.AllowDuplicates";i:7;s:18:"CSS.AllowImportant";i:7;s:15:"CSS.AllowTricky";i:7;s:16:"CSS.AllowedFonts";i:-8;s:21:"CSS.AllowedProperties";i:-8;s:17:"CSS.DefinitionRev";i:5;s:23:"CSS.ForbiddenProperties";i:8;s:16:"CSS.MaxImgLength";i:-1;s:15:"CSS.Proprietary";i:7;s:11:"CSS.Trusted";i:7;s:20:"Cache.DefinitionImpl";i:-1;s:20:"Core.DefinitionCache";O:8:"stdClass":2:{s:3:"key";s:20:"Cache.DefinitionImpl";s:7:"isAlias";b:1;}s:20:"Cache.SerializerPath";i:-1;s:27:"Cache.SerializerPermissions";i:-5;s:22:"Core.AggressivelyFixLt";i:7;s:29:"Core.AggressivelyRemoveScript";i:7;s:28:"Core.AllowHostnameUnderscore";i:7;s:23:"Core.AllowParseManyTags";i:7;s:18:"Core.CollectErrors";i:7;s:18:"Core.ColorKeywords";i:10;s:30:"Core.ConvertDocumentToFragment";i:7;s:24:"Core.AcceptFullDocuments";O:8:"stdClass":2:{s:3:"key";s:30:"Core.ConvertDocumentToFragment";s:7:"isAlias";b:1;}s:36:"Core.DirectLexLineNumberSyncInterval";i:5;s:20:"Core.DisableExcludes";i:7;s:15:"Core.EnableIDNA";i:7;s:13:"Core.Encoding";i:2;s:26:"Core.EscapeInvalidChildren";i:7;s:22:"Core.EscapeInvalidTags";i:7;s:29:"Core.EscapeNonASCIICharacters";i:7;s:19:"Core.HiddenElements";i:8;s:13:"Core.Language";i:1;s:24:"Core.LegacyEntityDecoder";i:7;s:14:"Core.LexerImpl";i:-11;s:24:"Core.MaintainLineNumbers";i:-7;s:22:"Core.NormalizeNewlines";i:7;s:21:"Core.RemoveInvalidImg";i:7;s:33:"Core.RemoveProcessingInstructions";i:7;s:25:"Core.RemoveScriptContents";i:-7;s:13:"Filter.Custom";i:9;s:34:"Filter.ExtractStyleBlocks.Escaping";i:7;s:33:"Filter.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:38:"FilterParam.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:31:"Filter.ExtractStyleBlocks.Scope";i:-1;s:30:"Filter.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:35:"FilterParam.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:34:"Filter.ExtractStyleBlocks.TidyImpl";i:-11;s:38:"FilterParam.ExtractStyleBlocksTidyImpl";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.TidyImpl";s:7:"isAlias";b:1;}s:25:"Filter.ExtractStyleBlocks";i:7;s:14:"Filter.YouTube";i:7;s:12:"HTML.Allowed";i:-4;s:22:"HTML.AllowedAttributes";i:-8;s:20:"HTML.AllowedComments";i:8;s:26:"HTML.AllowedCommentsRegexp";i:-1;s:20:"HTML.AllowedElements";i:-8;s:19:"HTML.AllowedModules";i:-8;s:23:"HTML.Attr.Name.UseCDATA";i:7;s:17:"HTML.BlockWrapper";i:1;s:16:"HTML.CoreModules";i:8;s:18:"HTML.CustomDoctype";i:-1;s:17:"HTML.DefinitionID";i:-1;s:18:"HTML.DefinitionRev";i:5;s:12:"HTML.Doctype";O:8:"stdClass":3:{s:4:"type";i:1;s:10:"allow_null";b:1;s:7:"allowed";a:5:{s:22:"HTML 4.01 Transitional";b:1;s:16:"HTML 4.01 Strict";b:1;s:22:"XHTML 1.0 Transitional";b:1;s:16:"XHTML 1.0 Strict";b:1;s:9:"XHTML 1.1";b:1;}}s:25:"HTML.FlashAllowFullScreen";i:7;s:24:"HTML.ForbiddenAttributes";i:8;s:22:"HTML.ForbiddenElements";i:8;s:10:"HTML.Forms";i:7;s:17:"HTML.MaxImgLength";i:-5;s:13:"HTML.Nofollow";i:7;s:11:"HTML.Parent";i:1;s:16:"HTML.Proprietary";i:7;s:14:"HTML.SafeEmbed";i:7;s:15:"HTML.SafeIframe";i:7;s:15:"HTML.SafeObject";i:7;s:18:"HTML.SafeScripting";i:8;s:11:"HTML.Strict";i:7;s:16:"HTML.TargetBlank";i:7;s:19:"HTML.TargetNoopener";i:7;s:21:"HTML.TargetNoreferrer";i:7;s:12:"HTML.TidyAdd";i:8;s:14:"HTML.TidyLevel";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:4:{s:4:"none";b:1;s:5:"light";b:1;s:6:"medium";b:1;s:5:"heavy";b:1;}}s:15:"HTML.TidyRemove";i:8;s:12:"HTML.Trusted";i:7;s:10:"HTML.XHTML";i:7;s:10:"Core.XHTML";O:8:"stdClass":2:{s:3:"key";s:10:"HTML.XHTML";s:7:"isAlias";b:1;}s:28:"Output.CommentScriptContents";i:7;s:26:"Core.CommentScriptContents";O:8:"stdClass":2:{s:3:"key";s:28:"Output.CommentScriptContents";s:7:"isAlias";b:1;}s:19:"Output.FixInnerHTML";i:7;s:18:"Output.FlashCompat";i:7;s:14:"Output.Newline";i:-1;s:15:"Output.SortAttr";i:7;s:17:"Output.TidyFormat";i:7;s:15:"Core.TidyFormat";O:8:"stdClass":2:{s:3:"key";s:17:"Output.TidyFormat";s:7:"isAlias";b:1;}s:17:"Test.ForceNoIconv";i:7;s:18:"URI.AllowedSchemes";i:8;s:8:"URI.Base";i:-1;s:17:"URI.DefaultScheme";i:-1;s:16:"URI.DefinitionID";i:-1;s:17:"URI.DefinitionRev";i:5;s:11:"URI.Disable";i:7;s:15:"Attr.DisableURI";O:8:"stdClass":2:{s:3:"key";s:11:"URI.Disable";s:7:"isAlias";b:1;}s:19:"URI.DisableExternal";i:7;s:28:"URI.DisableExternalResources";i:7;s:20:"URI.DisableResources";i:7;s:8:"URI.Host";i:-1;s:17:"URI.HostBlacklist";i:9;s:16:"URI.MakeAbsolute";i:7;s:9:"URI.Munge";i:-1;s:18:"URI.MungeResources";i:7;s:18:"URI.MungeSecretKey";i:-1;s:26:"URI.OverrideAllowedSchemes";i:7;s:20:"URI.SafeIframeRegexp";i:-1;}} \ No newline at end of file diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php index d34299522..543e3f8f1 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php @@ -142,11 +142,12 @@ class HTMLPurifier_ContentSets if ($return !== false) { return $return; } - - throw new Exception( + // error-out + trigger_error( 'Could not determine which ChildDef class to instantiate', E_USER_ERROR ); + return false; } /** diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php index 5a0e7b91c..00e509c85 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php @@ -24,7 +24,11 @@ class HTMLPurifier_Context public function register($name, &$ref) { if (array_key_exists($name, $this->_storage)) { - throw new Exception("Name $name produces collision, cannot re-register"); + trigger_error( + "Name $name produces collision, cannot re-register", + E_USER_ERROR + ); + return; } $this->_storage[$name] =& $ref; } @@ -39,7 +43,10 @@ class HTMLPurifier_Context { if (!array_key_exists($name, $this->_storage)) { if (!$ignore_error) { - throw new Exception("Attempted to retrieve non-existent variable $name"); + trigger_error( + "Attempted to retrieve non-existent variable $name", + E_USER_ERROR + ); } $var = null; // so we can return by reference return $var; @@ -54,7 +61,11 @@ class HTMLPurifier_Context public function destroy($name) { if (!array_key_exists($name, $this->_storage)) { - throw new Exception("Attempted to destroy non-existent variable $name"); + trigger_error( + "Attempted to destroy non-existent variable $name", + E_USER_ERROR + ); + return; } unset($this->_storage[$name]); } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php index 6ba9ad2d9..b82c6bb20 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php @@ -139,9 +139,8 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac continue; } $key = substr($filename, 0, strlen($filename) - 4); - $file = $dir . '/' . $filename; - if ($this->isOld($key, $config) && file_exists($file)) { - unlink($file); + if ($this->isOld($key, $config)) { + unlink($dir . '/' . $filename); } } closedir($dh); @@ -288,14 +287,13 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } elseif (filegroup($dir) === posix_getgid()) { $chmod = $chmod | 0070; } else { - // PHP's probably running as nobody, it is - // not obvious how to fix this (777 is probably - // bad if you are multi-user), let the user figure it out - $chmod = null; + // PHP's probably running as nobody, so we'll + // need to give global permissions + $chmod = $chmod | 0777; } trigger_error( - 'Directory ' . $dir . ' not writable. ' . - ($chmod === null ? '' : 'Please chmod to ' . decoct($chmod)), + 'Directory ' . $dir . ' not writable, ' . + 'please chmod to ' . decoct($chmod), E_USER_WARNING ); } else { diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,1cb20df370bd0f944e5a3321cc5041119545d67d,1.ser b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,1cb20df370bd0f944e5a3321cc5041119545d67d,1.ser new file mode 100644 index 000000000..e1f498187 Binary files /dev/null and b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,1cb20df370bd0f944e5a3321cc5041119545d67d,1.ser differ diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,b55df03349e7aaab0a2ad3ef8d72b34a72d0c414,1.ser b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,b55df03349e7aaab0a2ad3ef8d72b34a72d0c414,1.ser new file mode 100644 index 000000000..e8e38349c Binary files /dev/null and b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/HTML/4.15.0,b55df03349e7aaab0a2ad3ef8d72b34a72d0c414,1.ser differ diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/URI/4.15.0,3478238e680361cd87bf880f5b3cc50a1e7abc6c,1.ser b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/URI/4.15.0,3478238e680361cd87bf880f5b3cc50a1e7abc6c,1.ser new file mode 100644 index 000000000..f6d3e812b Binary files /dev/null and b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/URI/4.15.0,3478238e680361cd87bf880f5b3cc50a1e7abc6c,1.ser differ diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php index 3a0f4616a..fd1cc9be4 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php @@ -71,7 +71,7 @@ class HTMLPurifier_DefinitionCacheFactory return $this->caches[$method][$type]; } if (isset($this->implementations[$method]) && - class_exists($class = $this->implementations[$method])) { + class_exists($class = $this->implementations[$method], false)) { $cache = new $class($type); } else { if ($method != 'Serializer') { diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php index 9ad7b4b1e..acc1d64a6 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php @@ -86,7 +86,7 @@ class HTMLPurifier_DoctypeRegistry $doctype = $this->aliases[$doctype]; } if (!isset($this->doctypes[$doctype])) { - throw new Exception('Doctype ' . htmlspecialchars($doctype) . ' does not exist'); + trigger_error('Doctype ' . htmlspecialchars($doctype) . ' does not exist', E_USER_ERROR); $anon = new HTMLPurifier_Doctype($doctype); return $anon; } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php index 910181b20..d4791cc1b 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php @@ -12,7 +12,7 @@ class HTMLPurifier_Encoder */ private function __construct() { - throw new Exception('Cannot instantiate encoder, call methods statically'); + trigger_error('Cannot instantiate encoder, call methods statically', E_USER_ERROR); } /** @@ -390,7 +390,7 @@ class HTMLPurifier_Encoder $str = self::unsafeIconv($encoding, 'utf-8//IGNORE', $str); if ($str === false) { // $encoding is not a valid encoding - throw new Exception('Invalid encoding ' . $encoding); + trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR); return ''; } // If the string is bjorked by Shift_JIS or a similar encoding @@ -404,11 +404,12 @@ class HTMLPurifier_Encoder } $bug = HTMLPurifier_Encoder::testIconvTruncateBug(); if ($bug == self::ICONV_OK) { - throw new Exception('Encoding not supported, please install iconv'); + trigger_error('Encoding not supported, please install iconv', E_USER_ERROR); } else { - throw new Exception( + trigger_error( 'You have a buggy version of iconv, see https://bugs.php.net/bug.php?id=48147 ' . - 'and http://sourceware.org/bugzilla/show_bug.cgi?id=13541' + 'and http://sourceware.org/bugzilla/show_bug.cgi?id=13541', + E_USER_ERROR ); } } @@ -453,7 +454,7 @@ class HTMLPurifier_Encoder $str = mb_convert_encoding($str, 'ISO-8859-1', 'UTF-8'); return $str; } - throw new Exception('Encoding not supported'); + trigger_error('Encoding not supported', E_USER_ERROR); // You might be tempted to assume that the ASCII representation // might be OK, however, this is *not* universally true over all // encodings. So we take the conservative route here, rather @@ -544,9 +545,10 @@ class HTMLPurifier_Encoder } elseif (($c = strlen($r)) < 9000) { $code = self::ICONV_TRUNCATES; } elseif ($c > 9000) { - throw new Exception( + trigger_error( 'Your copy of iconv is extremely buggy. Please notify HTML Purifier maintainers: ' . - 'include your iconv version as per phpversion()' + 'include your iconv version as per phpversion()', + E_USER_ERROR ); } else { $code = self::ICONV_OK; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php index 1dcd10c7c..3ef2d09ec 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php @@ -5,7 +5,7 @@ // $config or $context to the callback functions. /** - * Handles referencing and dereferencing character entities + * Handles referencing and derefencing character entities */ class HTMLPurifier_EntityParser { @@ -116,8 +116,8 @@ class HTMLPurifier_EntityParser protected function entityCallback($matches) { $entity = $matches[0]; - $hex_part = isset($matches[1]) ? $matches[1] : null; - $dec_part = isset($matches[2]) ? $matches[2] : null; + $hex_part = @$matches[1]; + $dec_part = @$matches[2]; $named_part = empty($matches[3]) ? (empty($matches[4]) ? "" : $matches[4]) : $matches[3]; if ($hex_part !== NULL && $hex_part !== "") { return HTMLPurifier_Encoder::unichr(hexdec($hex_part)); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php index d52ae08dd..c1f41ee16 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php @@ -4,7 +4,7 @@ * Represents a pre or post processing filter on HTML Purifier's output * * Sometimes, a little ad-hoc fixing of HTML has to be done before - * it gets sent through HTML Purifier: you can use filters to achieve + * it gets sent through HTML Purifier: you can use filters to acheive * this effect. For instance, YouTube videos can be preserved using * this manner. You could have used a decorator for this task, but * PHP's support for them is not terribly robust, so we're going diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php index e7e3cac1a..66f70b0fc 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php @@ -54,11 +54,6 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter */ private $_enum_attrdef; - /** - * @type HTMLPurifier_AttrDef_Enum - */ - private $_universal_attrdef; - public function __construct() { $this->_tidy = new csstidy(); @@ -75,13 +70,6 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter 'focus' ) ); - $this->_universal_attrdef = new HTMLPurifier_AttrDef_Enum( - array( - 'initial', - 'inherit', - 'unset', - ) - ); } /** @@ -158,184 +146,175 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter foreach ($this->_tidy->css as $k => $decls) { // $decls are all CSS declarations inside an @ selector $new_decls = array(); - if (is_array($decls)) { - foreach ($decls as $selector => $style) { - $selector = trim($selector); - if ($selector === '') { - continue; - } // should not happen - // Parse the selector - // Here is the relevant part of the CSS grammar: - // - // ruleset - // : selector [ ',' S* selector ]* '{' ... - // selector - // : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]? - // combinator - // : '+' S* - // : '>' S* - // simple_selector - // : element_name [ HASH | class | attrib | pseudo ]* - // | [ HASH | class | attrib | pseudo ]+ - // element_name - // : IDENT | '*' - // ; - // class - // : '.' IDENT - // ; - // attrib - // : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* - // [ IDENT | STRING ] S* ]? ']' - // ; - // pseudo - // : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ] - // ; - // - // For reference, here are the relevant tokens: - // - // HASH #{name} - // IDENT {ident} - // INCLUDES == - // DASHMATCH |= - // STRING {string} - // FUNCTION {ident}\( - // - // And the lexical scanner tokens - // - // name {nmchar}+ - // nmchar [_a-z0-9-]|{nonascii}|{escape} - // nonascii [\240-\377] - // escape {unicode}|\\[^\r\n\f0-9a-f] - // unicode \\{h}}{1,6}(\r\n|[ \t\r\n\f])? - // ident -?{nmstart}{nmchar*} - // nmstart [_a-z]|{nonascii}|{escape} - // string {string1}|{string2} - // string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" - // string2 \'([^\n\r\f\\"]|\\{nl}|{escape})*\' - // - // We'll implement a subset (in order to reduce attack - // surface); in particular: - // - // - No Unicode support - // - No escapes support - // - No string support (by proxy no attrib support) - // - element_name is matched against allowed - // elements (some people might find this - // annoying...) - // - Pseudo-elements one of :first-child, :link, - // :visited, :active, :hover, :focus + foreach ($decls as $selector => $style) { + $selector = trim($selector); + if ($selector === '') { + continue; + } // should not happen + // Parse the selector + // Here is the relevant part of the CSS grammar: + // + // ruleset + // : selector [ ',' S* selector ]* '{' ... + // selector + // : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]? + // combinator + // : '+' S* + // : '>' S* + // simple_selector + // : element_name [ HASH | class | attrib | pseudo ]* + // | [ HASH | class | attrib | pseudo ]+ + // element_name + // : IDENT | '*' + // ; + // class + // : '.' IDENT + // ; + // attrib + // : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* + // [ IDENT | STRING ] S* ]? ']' + // ; + // pseudo + // : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ] + // ; + // + // For reference, here are the relevant tokens: + // + // HASH #{name} + // IDENT {ident} + // INCLUDES == + // DASHMATCH |= + // STRING {string} + // FUNCTION {ident}\( + // + // And the lexical scanner tokens + // + // name {nmchar}+ + // nmchar [_a-z0-9-]|{nonascii}|{escape} + // nonascii [\240-\377] + // escape {unicode}|\\[^\r\n\f0-9a-f] + // unicode \\{h}}{1,6}(\r\n|[ \t\r\n\f])? + // ident -?{nmstart}{nmchar*} + // nmstart [_a-z]|{nonascii}|{escape} + // string {string1}|{string2} + // string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" + // string2 \'([^\n\r\f\\"]|\\{nl}|{escape})*\' + // + // We'll implement a subset (in order to reduce attack + // surface); in particular: + // + // - No Unicode support + // - No escapes support + // - No string support (by proxy no attrib support) + // - element_name is matched against allowed + // elements (some people might find this + // annoying...) + // - Pseudo-elements one of :first-child, :link, + // :visited, :active, :hover, :focus - // handle ruleset - $selectors = array_map('trim', explode(',', $selector)); - $new_selectors = array(); - foreach ($selectors as $sel) { - // split on +, > and spaces - $basic_selectors = preg_split('/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE); - // even indices are chunks, odd indices are - // delimiters - $nsel = null; - $delim = null; // guaranteed to be non-null after - // two loop iterations - for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) { - $x = $basic_selectors[$i]; - if ($i % 2) { - // delimiter - if ($x === ' ') { - $delim = ' '; - } else { - $delim = ' ' . $x . ' '; - } + // handle ruleset + $selectors = array_map('trim', explode(',', $selector)); + $new_selectors = array(); + foreach ($selectors as $sel) { + // split on +, > and spaces + $basic_selectors = preg_split('/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE); + // even indices are chunks, odd indices are + // delimiters + $nsel = null; + $delim = null; // guaranteed to be non-null after + // two loop iterations + for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) { + $x = $basic_selectors[$i]; + if ($i % 2) { + // delimiter + if ($x === ' ') { + $delim = ' '; } else { - // simple selector - $components = preg_split('/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE); - $sdelim = null; - $nx = null; - for ($j = 0, $cc = count($components); $j < $cc; $j++) { - $y = $components[$j]; - if ($j === 0) { - if ($y === '*' || isset($html_definition->info[$y = strtolower($y)])) { - $nx = $y; - } else { - // $nx stays null; this matters - // if we don't manage to find - // any valid selector content, - // in which case we ignore the - // outer $delim - } - } elseif ($j % 2) { - // set delimiter - $sdelim = $y; + $delim = ' ' . $x . ' '; + } + } else { + // simple selector + $components = preg_split('/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE); + $sdelim = null; + $nx = null; + for ($j = 0, $cc = count($components); $j < $cc; $j++) { + $y = $components[$j]; + if ($j === 0) { + if ($y === '*' || isset($html_definition->info[$y = strtolower($y)])) { + $nx = $y; } else { - $attrdef = null; - if ($sdelim === '#') { - $attrdef = $this->_id_attrdef; - } elseif ($sdelim === '.') { - $attrdef = $this->_class_attrdef; - } elseif ($sdelim === ':') { - $attrdef = $this->_enum_attrdef; - } else { - throw new HTMLPurifier_Exception('broken invariant sdelim and preg_split'); - } - $r = $attrdef->validate($y, $config, $context); - if ($r !== false) { - if ($r !== true) { - $y = $r; - } - if ($nx === null) { - $nx = ''; - } - $nx .= $sdelim . $y; - } - } - } - if ($nx !== null) { - if ($nsel === null) { - $nsel = $nx; - } else { - $nsel .= $delim . $nx; + // $nx stays null; this matters + // if we don't manage to find + // any valid selector content, + // in which case we ignore the + // outer $delim } + } elseif ($j % 2) { + // set delimiter + $sdelim = $y; } else { - // delimiters to the left of invalid - // basic selector ignored + $attrdef = null; + if ($sdelim === '#') { + $attrdef = $this->_id_attrdef; + } elseif ($sdelim === '.') { + $attrdef = $this->_class_attrdef; + } elseif ($sdelim === ':') { + $attrdef = $this->_enum_attrdef; + } else { + throw new HTMLPurifier_Exception('broken invariant sdelim and preg_split'); + } + $r = $attrdef->validate($y, $config, $context); + if ($r !== false) { + if ($r !== true) { + $y = $r; + } + if ($nx === null) { + $nx = ''; + } + $nx .= $sdelim . $y; + } } } - } - if ($nsel !== null) { - if (!empty($scopes)) { - foreach ($scopes as $s) { - $new_selectors[] = "$s $nsel"; + if ($nx !== null) { + if ($nsel === null) { + $nsel = $nx; + } else { + $nsel .= $delim . $nx; } } else { - $new_selectors[] = $nsel; + // delimiters to the left of invalid + // basic selector ignored } } } - if (empty($new_selectors)) { + if ($nsel !== null) { + if (!empty($scopes)) { + foreach ($scopes as $s) { + $new_selectors[] = "$s $nsel"; + } + } else { + $new_selectors[] = $nsel; + } + } + } + if (empty($new_selectors)) { + continue; + } + $selector = implode(', ', $new_selectors); + foreach ($style as $name => $value) { + if (!isset($css_definition->info[$name])) { + unset($style[$name]); continue; } - $selector = implode(', ', $new_selectors); - foreach ($style as $name => $value) { - if (!isset($css_definition->info[$name])) { - unset($style[$name]); - continue; - } - $uni_ret = $this->_universal_attrdef->validate($value, $config, $context); - if ($uni_ret !== false) { - $style[$name] = $uni_ret; - continue; - } - $def = $css_definition->info[$name]; - $ret = $def->validate($value, $config, $context); - if ($ret === false) { - unset($style[$name]); - } else { - $style[$name] = $ret; - } + $def = $css_definition->info[$name]; + $ret = $def->validate($value, $config, $context); + if ($ret === false) { + unset($style[$name]); + } else { + $style[$name] = $ret; } - $new_decls[$selector] = $style; } - } else { - continue; + $new_decls[$selector] = $style; } $new_css[$k] = $new_decls; } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php index d86509ced..276d8362f 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php @@ -19,7 +19,7 @@ class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter $pre_regex = '#]+>.+?' . '(?:http:)?//www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?#s'; $pre_replace = '\1'; - return preg_replace($pre_regex, $pre_replace, (string)$html); + return preg_replace($pre_regex, $pre_replace, $html); } /** @@ -31,7 +31,7 @@ class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter public function postFilter($html, $config, $context) { $post_regex = '#((?:v|cp)/[A-Za-z0-9\-_=]+)#'; - return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), (string)$html); + return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html); } /** diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php index 457fa9054..eb56e2dfa 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php @@ -244,7 +244,7 @@ class HTMLPurifier_Generator // whitespace (in fact, most don't, at least for attributes // like alt, but an extra space at the end is barely // noticeable). Still, we have a configuration knob for - // this, since this transformation is not necessary if you + // this, since this transformation is not necesary if you // don't process user input with innerHTML or you don't plan // on supporting Internet Explorer. if ($this->_innerHTMLFix) { diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php index dc2c33c7f..9b7b334dd 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php @@ -264,8 +264,9 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition if (isset($this->info_content_sets['Block'][$block_wrapper])) { $this->info_block_wrapper = $block_wrapper; } else { - throw new Exception( - 'Cannot use non-block element as block wrapper' + trigger_error( + 'Cannot use non-block element as block wrapper', + E_USER_ERROR ); } @@ -275,7 +276,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition $this->info_parent = $parent; $this->info_parent_def = $def; } else { - throw new Exception('Cannot use unrecognized element as parent'); + trigger_error( + 'Cannot use unrecognized element as parent', + E_USER_ERROR + ); + $this->info_parent_def = $this->manager->getElement($this->info_parent, true); } // support template text diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php index f02a563e7..a9042a357 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php @@ -28,7 +28,7 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule // HTML 4.01 specifies that ins/del must not contain block // elements when used in an inline context, chameleon is - // a complicated workaround to achieve this effect + // a complicated workaround to acheive this effect // Inline context ! Block context (exclamation mark is // separator, see getChildDef for parsing) diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php index 71dfc7744..f7e7c91c0 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php @@ -28,28 +28,22 @@ class HTMLPurifier_HTMLModule_Iframe extends HTMLPurifier_HTMLModule if ($config->get('HTML.SafeIframe')) { $this->safe = true; } - $attrs = array( - 'src' => 'URI#embedded', - 'width' => 'Length', - 'height' => 'Length', - 'name' => 'ID', - 'scrolling' => 'Enum#yes,no,auto', - 'frameborder' => 'Enum#0,1', - 'longdesc' => 'URI', - 'marginheight' => 'Pixels', - 'marginwidth' => 'Pixels', - ); - - if ($config->get('HTML.Trusted')) { - $attrs['allowfullscreen'] = 'Bool#allowfullscreen'; - } - $this->addElement( 'iframe', 'Inline', 'Flow', 'Common', - $attrs + array( + 'src' => 'URI#embedded', + 'width' => 'Length', + 'height' => 'Length', + 'name' => 'ID', + 'scrolling' => 'Enum#yes,no,auto', + 'frameborder' => 'Enum#0,1', + 'longdesc' => 'URI', + 'marginheight' => 'Pixels', + 'marginwidth' => 'Pixels', + ) ); } } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php index d1afde0f8..a0d48924d 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php @@ -2,7 +2,7 @@ /** * XHTML 1.1 Ruby Annotation Module, defines elements that indicate - * short runs of text alongside base text for annotation or pronunciation. + * short runs of text alongside base text for annotation or pronounciation. */ class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule { diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php index bd926dc26..12173ba70 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php @@ -112,8 +112,9 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule return; } if (!isset($this->fixesForLevel[$this->defaultLevel])) { - throw new Exception( - 'Default level ' . $this->defaultLevel . ' does not exist' + trigger_error( + 'Default level ' . $this->defaultLevel . ' does not exist', + E_USER_ERROR ); return; } @@ -161,7 +162,8 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule $e->$type = $fix; break; default: - throw new Exception("Fix type $type not supported"); + trigger_error("Fix type $type not supported", E_USER_ERROR); + break; } } } @@ -219,7 +221,6 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule */ public function makeFixes() { - return array(); } } diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php index 5b3f3d50c..a995161b2 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php @@ -1,7 +1,7 @@ dir . '/Language/classes/' . $code . '.php'; - if (file_exists($file) || class_exists($class)) { + if (file_exists($file) || class_exists($class, false)) { $lang = new $class($config, $context); } else { // Go fallback @@ -173,8 +173,14 @@ class HTMLPurifier_LanguageFactory // infinite recursion guard if (isset($languages_seen[$code])) { - throw new Exception('Circular fallback reference in language ' . $code); + trigger_error( + 'Circular fallback reference in language ' . + $code, + E_USER_ERROR + ); + $fallback = 'en'; } + $language_seen[$code] = true; // load the fallback recursively $this->loadLanguage($fallback); diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php index 793edc89a..c21f36491 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php @@ -101,7 +101,7 @@ class HTMLPurifier_Lexer break; } - if (class_exists('DOMDocument') && + if (class_exists('DOMDocument', false) && method_exists('DOMDocument', 'loadHTML') && !extension_loaded('domxml') ) { @@ -238,7 +238,7 @@ class HTMLPurifier_Lexer */ public function tokenizeHTML($string, $config, $context) { - throw new Exception('Call to abstract class'); + trigger_error('Call to abstract class', E_USER_ERROR); } /** @@ -269,6 +269,20 @@ class HTMLPurifier_Lexer ); } + /** + * Special Internet Explorer conditional comments should be removed. + * @param string $string HTML string to process. + * @return string HTML with conditional comments removed. + */ + protected static function removeIEConditional($string) + { + return preg_replace( + '##si', // probably should generalize for all strings + '', + $string + ); + } + /** * Callback function for escapeCDATA() that does the work. * @@ -309,6 +323,8 @@ class HTMLPurifier_Lexer // escape CDATA $html = $this->escapeCDATA($html); + $html = $this->removeIEConditional($html); + // extract body from document if applicable if ($config->get('Core.ConvertDocumentToFragment')) { $e = false; diff --git a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php index de79aaaec..ca5f25b84 100644 --- a/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php +++ b/src/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php @@ -52,7 +52,14 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer // attempt to armor stray angled brackets that cannot possibly // form tags and thus are probably being used as emoticons if ($config->get('Core.AggressivelyFixLt')) { - $html = $this->aggressivelyFixLt($html); + $char = '[^a-z!\/]'; + $comment = "/|\z)/is"; + $html = preg_replace_callback($comment, array($this, 'callbackArmorCommentEntities'), $html); + do { + $old = $html; + $html = preg_replace("/<($char)/i", '<\\1', $html); + } while ($html !== $old); + $html = preg_replace_callback($comment, array($this, 'callbackUndoCommentSubst'), $html); // fix comments } // preprocess html, essential for UTF-8 @@ -65,9 +72,6 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer if ($config->get('Core.AllowParseManyTags') && defined('LIBXML_PARSEHUGE')) { $options |= LIBXML_PARSEHUGE; } - if ($config->get('Core.RemoveBlanks') && defined('LIBXML_NOBLANKS')) { - $options |= LIBXML_NOBLANKS; - } set_error_handler(array($this, 'muteErrorHandler')); // loadHTML() fails on PHP 5.3 when second parameter is given @@ -100,6 +104,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer * To iterate is human, to recurse divine - L. Peter Deutsch * @param DOMNode $node DOMNode to be tokenized. * @param HTMLPurifier_Token[] $tokens Array-list of already tokenized tokens. + * @return HTMLPurifier_Token of node appended to previously passed tokens. */ protected function tokenizeDOM($node, &$tokens, $config) { @@ -281,7 +286,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer */ public function callbackUndoCommentSubst($matches) { - return ''; - - while (($startPos = strpos($html, $startTag, $offset)) !== false) { - $startPos += strlen($startTag); // Move past ` + 页面自动 跳转 等待时间: - + var interval = setInterval(function(){ + var time = --wait.innerHTML; + if(time <= 0) { + location.href = href; + clearInterval(interval); + }; + }, 1000); + })(); + diff --git a/src/vendor/maennchen/zipstream-php/CHANGELOG.md b/src/vendor/maennchen/zipstream-php/CHANGELOG.md new file mode 100644 index 000000000..b1979abcc --- /dev/null +++ b/src/vendor/maennchen/zipstream-php/CHANGELOG.md @@ -0,0 +1,51 @@ +# CHANGELOG for ZipStream-PHP + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [2.1.0] - 2020-06-01 +### Changed +- Don't execute ob_flush() when output buffering is not enabled (#152) +- Fix inconsistent return type on 32-bit systems (#149) Fix #144 +- Use mbstring polyfill (#151) +- Promote 7zip usage over unzip to avoid UTF-8 issues (#147) + +## [2.0.0] - 2020-02-22 +### Breaking change +- Only the self opened streams will be closed (#139) +If you were relying on ZipStream to close streams that the library didn't open, +you'll need to close them yourself now. + +### Changed +- Minor change to data descriptor (#136) + +## [1.2.0] - 2019-07-11 + +### Added +- Option to flush output buffer after every write (#122) + +## [1.1.0] - 2019-04-30 + +### Fixed +- Honor last-modified timestamps set via `ZipStream\Option\File::setTime()` (#106) +- Documentation regarding output of HTTP headers +- Test warnings with PHPUnit (#109) + +### Added +- Test for FileNotReadableException (#114) +- Size attribute to File options (#113) +- Tests on PHP 7.3 (#108) + +## [1.0.0] - 2019-04-17 + +### Breaking changes +- Mininum PHP version is now 7.1 +- Options are now passed to the ZipStream object via the Option\Archive object. See the wiki for available options and code examples + +### Added +- Add large file support with Zip64 headers + +### Changed +- Major refactoring and code cleanup diff --git a/src/vendor/maennchen/zipstream-php/CONTRIBUTING.md b/src/vendor/maennchen/zipstream-php/CONTRIBUTING.md new file mode 100644 index 000000000..f8ef5a573 --- /dev/null +++ b/src/vendor/maennchen/zipstream-php/CONTRIBUTING.md @@ -0,0 +1,25 @@ +# ZipStream Readme for Contributors +## Code styling +### Indention +For spaces are used to indent code. The convention is [K&R](http://en.wikipedia.org/wiki/Indent_style#K&R) + +### Comments +Double Slashes are used for an one line comment. + +Classes, Variables, Methods etc: + +```php +/** + * My comment + * + * @myanotation like @param etc. + */ +``` + +## Pull requests +Feel free to submit pull requests. + +## Testing +For every new feature please write a new PHPUnit test. + +Before every commit execute `./vendor/bin/phpunit` to check if your changes wrecked something: diff --git a/src/vendor/maennchen/zipstream-php/README.md b/src/vendor/maennchen/zipstream-php/README.md index 155a26582..c489867d6 100644 --- a/src/vendor/maennchen/zipstream-php/README.md +++ b/src/vendor/maennchen/zipstream-php/README.md @@ -1,17 +1,11 @@ # ZipStream-PHP -[![Main Branch](https://github.com/maennchen/ZipStream-PHP/actions/workflows/branch_main.yml/badge.svg)](https://github.com/maennchen/ZipStream-PHP/actions/workflows/branch_main.yml) -[![Coverage Status](https://coveralls.io/repos/github/maennchen/ZipStream-PHP/badge.svg?branch=main)](https://coveralls.io/github/maennchen/ZipStream-PHP?branch=main) +![.github/workflows/php.yml](https://github.com/maennchen/ZipStream-PHP/workflows/.github/workflows/php.yml/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/maennchen/ZipStream-PHP/badge.svg?branch=master)](https://coveralls.io/github/maennchen/ZipStream-PHP?branch=master) [![Latest Stable Version](https://poser.pugx.org/maennchen/zipstream-php/v/stable)](https://packagist.org/packages/maennchen/zipstream-php) [![Total Downloads](https://poser.pugx.org/maennchen/zipstream-php/downloads)](https://packagist.org/packages/maennchen/zipstream-php) [![Financial Contributors on Open Collective](https://opencollective.com/zipstream/all/badge.svg?label=financial+contributors)](https://opencollective.com/zipstream) [![License](https://img.shields.io/github/license/maennchen/zipstream-php.svg)](LICENSE) -## Unstable Branch - -The `main` branch is not stable. Please see the -[releases](https://github.com/maennchen/ZipStream-PHP/releases) for a stable -version. - ## Overview A fast and simple streaming zip file downloader for PHP. Using this library will save you from having to write the Zip to disk. You can directly send it to the user, which is much faster. It can work with S3 buckets or any PSR7 Stream. @@ -26,10 +20,7 @@ Simply add a dependency on maennchen/zipstream-php to your project's composer.js composer require maennchen/zipstream-php ``` -## Usage - -For detailed instructions, please check the -[Documentation](https://maennchen.dev/ZipStream-PHP/). +## Usage and options Here's a simple example: @@ -50,20 +41,41 @@ $zip->addFile('hello.txt', 'This is the contents of hello.txt'); // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg' $zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg'); +// add a file named 'goodbye.txt' from an open stream resource +$fp = tmpfile(); +fwrite($fp, 'The quick brown fox jumped over the lazy dog.'); +rewind($fp); +$zip->addFileFromStream('goodbye.txt', $fp); +fclose($fp); + // finish the zip stream $zip->finish(); ``` +You can also add comments, modify file timestamps, and customize (or +disable) the HTTP headers. It is also possible to specify the storage method when adding files, +the current default storage method is 'deflate' i.e files are stored with Compression mode 0x08. + +See the [Wiki](https://github.com/maennchen/ZipStream-PHP/wiki) for details. + +## Known issues + +The native Mac OS archive extraction tool prior to macOS 10.15 might not open archives in some conditions. A workaround is to disable the Zip64 feature with the option `$opt->setEnableZip64(false)`. This limits the archive to 4 Gb and 64k files but will allow users on macOS 10.14 and below to open them without issue. See #116. + +The linux `unzip` utility might not handle properly unicode characters. It is recommended to extract with another tool like [7-zip](https://www.7-zip.org/). See [#146](https://github.com/maennchen/ZipStream-PHP/issues/146). + +It is the responsability of the client code to make sure that files are not saved with the same path, as it is not possible for the library to figure it out while streaming a zip. See [#154](https://github.com/maennchen/ZipStream-PHP/issues/154). + ## Upgrade to version 2.0.0 -- Only the self opened streams will be closed (#139) - If you were relying on ZipStream to close streams that the library didn't open, - you'll need to close them yourself now. +* Only the self opened streams will be closed (#139) +If you were relying on ZipStream to close streams that the library didn't open, +you'll need to close them yourself now. ## Upgrade to version 1.0.0 -- All options parameters to all function have been moved from an `array` to structured option objects. See [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Available-options) for examples. -- The whole library has been refactored. The minimal PHP requirement has been raised to PHP 7.1. +* All options parameters to all function have been moved from an `array` to structured option objects. See [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Available-options) for examples. +* The whole library has been refactored. The minimal PHP requirement has been raised to PHP 7.1. ## Usage with Symfony and S3 @@ -71,23 +83,21 @@ You can find example code on [the wiki](https://github.com/maennchen/ZipStream-P ## Contributing -ZipStream-PHP is a collaborative project. Please take a look at the -[.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) file. +ZipStream-PHP is a collaborative project. Please take a look at the [CONTRIBUTING.md](CONTRIBUTING.md) file. ## About the Authors -- Paul Duncan - https://pablotron.org/ -- Jonatan Männchen - https://maennchen.dev -- Jesse G. Donat - https://donatstudios.com -- Nicolas CARPi - https://www.deltablot.com -- Nik Barham - https://www.brokencube.co.uk +* Paul Duncan - https://pablotron.org/ +* Jonatan Männchen - https://maennchen.dev +* Jesse G. Donat - https://donatstudios.com +* Nicolas CARPi - https://www.deltablot.com +* Nik Barham - https://www.brokencube.co.uk ## Contributors ### Code Contributors -This project exists thanks to all the people who contribute. -[[Contribute](.github/CONTRIBUTING.md)]. +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ### Financial Contributors diff --git a/src/vendor/maennchen/zipstream-php/composer.json b/src/vendor/maennchen/zipstream-php/composer.json index 47eee14f6..78943cf88 100644 --- a/src/vendor/maennchen/zipstream-php/composer.json +++ b/src/vendor/maennchen/zipstream-php/composer.json @@ -33,18 +33,7 @@ "ext-zip": "*", "mikey179/vfsstream": "^1.6", "vimeo/psalm": "^4.1", - "php-coveralls/php-coveralls": "^2.4", - "friendsofphp/php-cs-fixer": "^3.9" - }, - "scripts": { - "format": "php-cs-fixer fix", - "test": "composer run test:unit && composer run test:formatted && composer run test:lint", - "test:unit": "phpunit --coverage-clover=coverage.clover.xml", - "test:formatted": "composer run format -- --dry-run --stop-on-violation --using-cache=no", - "test:lint": "psalm --stats --show-info --find-unused-psalm-suppress", - "coverage:report": "php-coveralls --coverage_clover=coverage.clover.xml --json_path=coveralls-upload.json -v", - "install:tools": "phive install --trust-gpg-keys 0x67F861C3D889C656", - "docs:generate": "tools/phpdocumentor --sourcecode" + "php-coveralls/php-coveralls": "^2.4" }, "autoload": { "psr-4": { @@ -52,25 +41,6 @@ } }, "archive": { - "exclude": [ - "/composer.lock", - "/docs", - "/.gitattributes", - "/.github", - "/.gitignore", - "/guides", - "/.phive", - "/.php-cs-fixer.cache", - "/.php-cs-fixer.dist.php", - "/.phpdoc", - "/phpdoc.dist.xml", - "/.phpunit.result.cache", - "/phpunit.xml.dist", - "/psalm.xml", - "/test", - "/tools", - "/.tool-versions", - "/vendor" - ] + "exclude": ["/test", "/CHANGELOG.md", "/CONTRIBUTING.md", "/phpunit.xml.dist", "/psalm.xml"] } } diff --git a/src/vendor/maennchen/zipstream-php/src/Bigint.php b/src/vendor/maennchen/zipstream-php/src/Bigint.php index f2565e980..ff84d0d54 100644 --- a/src/vendor/maennchen/zipstream-php/src/Bigint.php +++ b/src/vendor/maennchen/zipstream-php/src/Bigint.php @@ -1,5 +1,4 @@ fillBytes($value, 0, 8); } + /** + * Fill the bytes field with int + * + * @param int $value + * @param int $start + * @param int $count + * @return void + */ + protected function fillBytes(int $value, int $start, int $count): void + { + for ($i = 0; $i < $count; $i++) { + $this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF; + $value >>= 8; + } + } + /** * Get an instance * @@ -43,7 +58,7 @@ class Bigint */ public static function fromLowHigh(int $low, int $high): self { - $bigint = new self(); + $bigint = new Bigint(); $bigint->fillBytes($low, 0, 4); $bigint->fillBytes($high, 4, 4); return $bigint; @@ -135,7 +150,7 @@ class Bigint * @param Bigint $other * @return Bigint */ - public function add(self $other): self + public function add(Bigint $other): Bigint { $result = clone $this; $overflow = false; @@ -151,24 +166,8 @@ class Bigint } } if ($overflow) { - throw new OverflowException(); + throw new OverflowException; } return $result; } - - /** - * Fill the bytes field with int - * - * @param int $value - * @param int $start - * @param int $count - * @return void - */ - protected function fillBytes(int $value, int $start, int $count): void - { - for ($i = 0; $i < $count; $i++) { - $this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF; - $value >>= 8; - } - } } diff --git a/src/vendor/maennchen/zipstream-php/src/DeflateStream.php b/src/vendor/maennchen/zipstream-php/src/DeflateStream.php index 7dc4d3a46..d6c272885 100644 --- a/src/vendor/maennchen/zipstream-php/src/DeflateStream.php +++ b/src/vendor/maennchen/zipstream-php/src/DeflateStream.php @@ -1,5 +1,4 @@ $options->getComment(), 'method' => $options->getMethod(), 'deflateLevel' => $options->getDeflateLevel(), - 'time' => $options->getTime(), + 'time' => $options->getTime() ]; $this->filter = stream_filter_append( $this->stream, diff --git a/src/vendor/maennchen/zipstream-php/src/Exception.php b/src/vendor/maennchen/zipstream-php/src/Exception.php index 03a87672a..18ccfbbdc 100644 --- a/src/vendor/maennchen/zipstream-php/src/Exception.php +++ b/src/vendor/maennchen/zipstream-php/src/Exception.php @@ -1,5 +1,4 @@ bits |= self::BIT_EFS_UTF8; + if (!mb_check_encoding($name, 'UTF-8') || + !mb_check_encoding($comment, 'UTF-8')) { + throw new EncodingException( + 'File name and comment should use UTF-8 ' . + 'if one of them does not fit into ASCII range.' + ); } + $this->bits |= self::BIT_EFS_UTF8; } if ($this->method->equals(Method::DEFLATE())) { $this->version = Version::DEFLATE(); } - $force = (bool)($this->bits & self::BIT_ZERO_HEADER) && + $force = (boolean)($this->bits & self::BIT_ZERO_HEADER) && $this->zip->opt->isEnableZip64(); $footer = $this->buildZip64ExtraBlock($force); @@ -227,97 +228,6 @@ class File return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $filename); } - /** - * Create and send data descriptor footer for this file. - * - * @return void - */ - public function addFileFooter(): void - { - if ($this->bits & self::BIT_ZERO_HEADER) { - // compressed and uncompressed size - $sizeFormat = 'V'; - if ($this->zip->opt->isEnableZip64()) { - $sizeFormat = 'P'; - } - $fields = [ - ['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE], - ['V', $this->crc], // CRC32 - [$sizeFormat, $this->zlen], // Length of compressed data - [$sizeFormat, $this->len], // Length of original data - ]; - - $footer = ZipStream::packFields($fields); - $this->zip->send($footer); - } else { - $footer = ''; - } - $this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer))); - $this->zip->addToCdr($this); - } - - public function processStream(StreamInterface $stream): void - { - $this->zlen = new Bigint(); - $this->len = new Bigint(); - - if ($this->zip->opt->isZeroHeader()) { - $this->processStreamWithZeroHeader($stream); - } else { - $this->processStreamWithComputedHeader($stream); - } - } - - /** - * Send CDR record for specified file. - * - * @return string - */ - public function getCdrFile(): string - { - $name = static::filterFilename($this->name); - - // get attributes - $comment = $this->opt->getComment(); - - // get dos timestamp - $time = static::dosTime($this->opt->getTime()->getTimestamp()); - - $footer = $this->buildZip64ExtraBlock(); - - $fields = [ - ['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature - ['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version - ['v', $this->version->getValue()], // Extract by version - ['v', $this->bits], // General purpose bit flags - data descriptor flag set - ['v', $this->method->getValue()], // Compression method - ['V', $time], // Timestamp (DOS Format) - ['V', $this->crc], // CRC32 - ['V', $this->zlen->getLowFF()], // Compressed Data Length - ['V', $this->len->getLowFF()], // Original Data Length - ['v', strlen($name)], // Length of filename - ['v', strlen($footer)], // Extra data len (see above) - ['v', strlen($comment)], // Length of comment - ['v', 0], // Disk number - ['v', 0], // Internal File Attributes - ['V', 32], // External File Attributes - ['V', $this->ofs->getLowFF()], // Relative offset of local header - ]; - - // pack fields, then append name and comment - $header = ZipStream::packFields($fields); - - return $header . $name . $footer . $comment; - } - - /** - * @return Bigint - */ - public function getTotalLength(): Bigint - { - return $this->totalLength; - } - /** * Convert a UNIX timestamp to a DOS timestamp. * @@ -331,14 +241,14 @@ class File // set lower-bound on dates if ($d['year'] < 1980) { - $d = [ + $d = array( 'year' => 1980, 'mon' => 1, 'mday' => 1, 'hours' => 0, 'minutes' => 0, - 'seconds' => 0, - ]; + 'seconds' => 0 + ); } // remove extra years from 1980 @@ -356,6 +266,7 @@ class File protected function buildZip64ExtraBlock(bool $force = false): string { + $fields = []; if ($this->len->isOver32($force)) { $fields[] = ['P', $this->len]; // Length of original data @@ -392,6 +303,49 @@ class File return ZipStream::packFields($fields); } + /** + * Create and send data descriptor footer for this file. + * + * @return void + */ + + public function addFileFooter(): void + { + + if ($this->bits & self::BIT_ZERO_HEADER) { + // compressed and uncompressed size + $sizeFormat = 'V'; + if ($this->zip->opt->isEnableZip64()) { + $sizeFormat = 'P'; + } + $fields = [ + ['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE], + ['V', $this->crc], // CRC32 + [$sizeFormat, $this->zlen], // Length of compressed data + [$sizeFormat, $this->len], // Length of original data + ]; + + $footer = ZipStream::packFields($fields); + $this->zip->send($footer); + } else { + $footer = ''; + } + $this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer))); + $this->zip->addToCdr($this); + } + + public function processStream(StreamInterface $stream): void + { + $this->zlen = new Bigint(); + $this->len = new Bigint(); + + if ($this->zip->opt->isZeroHeader()) { + $this->processStreamWithZeroHeader($stream); + } else { + $this->processStreamWithComputedHeader($stream); + } + } + protected function processStreamWithZeroHeader(StreamInterface $stream): void { $this->bits |= self::BIT_ZERO_HEADER; @@ -409,7 +363,7 @@ class File $data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE); $total += strlen($data); if ($size > 0 && $total > $size) { - $data = substr($data, 0, strlen($data)-($total - $size)); + $data = substr($data, 0 , strlen($data)-($total - $size)); } $this->deflateData($stream, $data, $options); if ($options & self::SEND) { @@ -480,4 +434,54 @@ class File $this->readStream($stream, self::SEND); $this->addFileFooter(); } + + /** + * Send CDR record for specified file. + * + * @return string + */ + public function getCdrFile(): string + { + $name = static::filterFilename($this->name); + + // get attributes + $comment = $this->opt->getComment(); + + // get dos timestamp + $time = static::dosTime($this->opt->getTime()->getTimestamp()); + + $footer = $this->buildZip64ExtraBlock(); + + $fields = [ + ['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature + ['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version + ['v', $this->version->getValue()], // Extract by version + ['v', $this->bits], // General purpose bit flags - data descriptor flag set + ['v', $this->method->getValue()], // Compression method + ['V', $time], // Timestamp (DOS Format) + ['V', $this->crc], // CRC32 + ['V', $this->zlen->getLowFF()], // Compressed Data Length + ['V', $this->len->getLowFF()], // Original Data Length + ['v', strlen($name)], // Length of filename + ['v', strlen($footer)], // Extra data len (see above) + ['v', strlen($comment)], // Length of comment + ['v', 0], // Disk number + ['v', 0], // Internal File Attributes + ['V', 32], // External File Attributes + ['V', $this->ofs->getLowFF()] // Relative offset of local header + ]; + + // pack fields, then append name and comment + $header = ZipStream::packFields($fields); + + return $header . $name . $footer . $comment; + } + + /** + * @return Bigint + */ + public function getTotalLength(): Bigint + { + return $this->totalLength; + } } diff --git a/src/vendor/maennchen/zipstream-php/src/Option/Archive.php b/src/vendor/maennchen/zipstream-php/src/Option/Archive.php index 374dd1deb..21d14d8c5 100644 --- a/src/vendor/maennchen/zipstream-php/src/Option/Archive.php +++ b/src/vendor/maennchen/zipstream-php/src/Option/Archive.php @@ -1,5 +1,4 @@ 4 GB or file count > 64k) @@ -61,7 +54,6 @@ final class Archive * @var bool */ private $enableZip64 = true; - /** * Enable streaming files with single read where * general purpose bit 3 indicates local file header @@ -72,7 +64,6 @@ final class Archive * @var bool */ private $zeroHeader = false; - /** * Enable reading file stat for determining file size. * When a 32-bit system reads file size that is @@ -86,13 +77,11 @@ final class Archive * @var bool */ private $statFiles = true; - /** * Enable flush after every write to output stream. * @var bool */ private $flushOutput = false; - /** * HTTP Content-Disposition. Defaults to * 'attachment', where @@ -104,7 +93,6 @@ final class Archive * @var string */ private $contentDisposition = 'attachment'; - /** * Note that this does nothing if you are * not sending HTTP headers. @@ -112,7 +100,6 @@ final class Archive * @var string */ private $contentType = 'application/x-zip'; - /** * @var int */ @@ -172,12 +159,12 @@ final class Archive $this->sendHttpHeaders = $sendHttpHeaders; } - public function getHttpHeaderCallback(): callable + public function getHttpHeaderCallback(): Callable { return $this->httpHeaderCallback; } - public function setHttpHeaderCallback(callable $httpHeaderCallback): void + public function setHttpHeaderCallback(Callable $httpHeaderCallback): void { $this->httpHeaderCallback = $httpHeaderCallback; } diff --git a/src/vendor/maennchen/zipstream-php/src/Option/File.php b/src/vendor/maennchen/zipstream-php/src/Option/File.php index 37e37ced6..05ff7b5ee 100644 --- a/src/vendor/maennchen/zipstream-php/src/Option/File.php +++ b/src/vendor/maennchen/zipstream-php/src/Option/File.php @@ -1,5 +1,4 @@ stream = $stream; } - /** - * Reads all data from the stream into a string, from the beginning to end. - * - * This method MUST attempt to seek to the beginning of the stream before - * reading data and read the stream until the end is reached. - * - * Warning: This could attempt to load a large amount of data into memory. - * - * This method MUST NOT raise an exception in order to conform with PHP's - * string casting operations. - * - * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring - * @return string - */ - public function __toString(): string - { - try { - $this->seek(0); - } catch (RuntimeException $e) { - } - return (string) stream_get_contents($this->stream); - } - /** * Closes the stream and any underlying resources. * @@ -75,6 +49,28 @@ class Stream implements StreamInterface return $result; } + /** + * Reads all data from the stream into a string, from the beginning to end. + * + * This method MUST attempt to seek to the beginning of the stream before + * reading data and read the stream until the end is reached. + * + * Warning: This could attempt to load a large amount of data into memory. + * + * This method MUST NOT raise an exception in order to conform with PHP's + * string casting operations. + * + * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring + * @return string + */ + public function __toString(): string + { + try { + $this->seek(0); + } catch (RuntimeException $e) {} + return (string) stream_get_contents($this->stream); + } + /** * Seek to a position in the stream. * @@ -90,10 +86,10 @@ class Stream implements StreamInterface public function seek($offset, $whence = SEEK_SET): void { if (!$this->isSeekable()) { - throw new RuntimeException(); + throw new RuntimeException; } if (fseek($this->stream, $offset, $whence) !== 0) { - throw new RuntimeException(); + throw new RuntimeException; } } @@ -146,7 +142,7 @@ class Stream implements StreamInterface { $position = ftell($this->stream); if ($position === false) { - throw new RuntimeException(); + throw new RuntimeException; } return $position; } @@ -186,12 +182,12 @@ class Stream implements StreamInterface public function write($string): int { if (!$this->isWritable()) { - throw new RuntimeException(); + throw new RuntimeException; } if (fwrite($this->stream, $string) === false) { - throw new RuntimeException(); + throw new RuntimeException; } - return mb_strlen($string); + return \mb_strlen($string); } /** @@ -216,16 +212,16 @@ class Stream implements StreamInterface * call returns fewer bytes. * @return string Returns the data read from the stream, or an empty string * if no bytes are available. - * @throws RuntimeException if an error occurs. + * @throws \RuntimeException if an error occurs. */ public function read($length): string { if (!$this->isReadable()) { - throw new RuntimeException(); + throw new RuntimeException; } $result = fread($this->stream, $length); if ($result === false) { - throw new RuntimeException(); + throw new RuntimeException; } return $result; } @@ -248,17 +244,17 @@ class Stream implements StreamInterface * Returns the remaining contents in a string * * @return string - * @throws RuntimeException if unable to read or an error occurs while + * @throws \RuntimeException if unable to read or an error occurs while * reading. */ public function getContents(): string { if (!$this->isReadable()) { - throw new RuntimeException(); + throw new RuntimeException; } $result = stream_get_contents($this->stream); if ($result === false) { - throw new RuntimeException(); + throw new RuntimeException; } return $result; } diff --git a/src/vendor/maennchen/zipstream-php/src/ZipStream.php b/src/vendor/maennchen/zipstream-php/src/ZipStream.php index 71ea4ed8e..d281d259f 100644 --- a/src/vendor/maennchen/zipstream-php/src/ZipStream.php +++ b/src/vendor/maennchen/zipstream-php/src/ZipStream.php @@ -1,5 +1,4 @@ clear(); } + /** + * Send ZIP64 CDR EOF (Central Directory Record End-of-File) record. + * + * @return void + */ + protected function addCdr64Eof(): void + { + $num_files = count($this->files); + $cdr_length = $this->cdr_ofs; + $cdr_offset = $this->ofs; + + $fields = [ + ['V', static::ZIP64_CDR_EOF_SIGNATURE], // ZIP64 end of central file header signature + ['P', 44], // Length of data below this header (length of block - 12) = 44 + ['v', static::ZIP_VERSION_MADE_BY], // Made by version + ['v', Version::ZIP64], // Extract by version + ['V', 0x00], // disk number + ['V', 0x00], // no of disks + ['P', $num_files], // no of entries on disk + ['P', $num_files], // no of entries in cdr + ['P', $cdr_length], // CDR size + ['P', $cdr_offset], // CDR offset + ]; + + $ret = static::packFields($fields); + $this->send($ret); + } + /** * Create a format string and argument list for pack(), then call * pack() and return the result. @@ -454,62 +476,6 @@ class ZipStream } } - /** - * Is this file larger than large_file_size? - * - * @param string $path - * @return bool - */ - public function isLargeFile(string $path): bool - { - if (!$this->opt->isStatFiles()) { - return false; - } - $stat = stat($path); - return $stat['size'] > $this->opt->getLargeFileSize(); - } - - /** - * Save file attributes for trailing CDR record. - * - * @param File $file - * @return void - */ - public function addToCdr(File $file): void - { - $file->ofs = $this->ofs; - $this->ofs = $this->ofs->add($file->getTotalLength()); - $this->files[] = $file->getCdrFile(); - } - - /** - * Send ZIP64 CDR EOF (Central Directory Record End-of-File) record. - * - * @return void - */ - protected function addCdr64Eof(): void - { - $num_files = count($this->files); - $cdr_length = $this->cdr_ofs; - $cdr_offset = $this->ofs; - - $fields = [ - ['V', static::ZIP64_CDR_EOF_SIGNATURE], // ZIP64 end of central file header signature - ['P', 44], // Length of data below this header (length of block - 12) = 44 - ['v', static::ZIP_VERSION_MADE_BY], // Made by version - ['v', Version::ZIP64], // Extract by version - ['V', 0x00], // disk number - ['V', 0x00], // no of disks - ['P', $num_files], // no of entries on disk - ['P', $num_files], // no of entries in cdr - ['P', $cdr_length], // CDR size - ['P', $cdr_offset], // CDR offset - ]; - - $ret = static::packFields($fields); - $this->send($ret); - } - /** * Send HTTP headers for this stream. * @@ -529,13 +495,13 @@ class ZipStream $disposition .= "; filename*=UTF-8''{$urlencoded}"; } - $headers = [ + $headers = array( 'Content-Type' => $this->opt->getContentType(), 'Content-Disposition' => $disposition, 'Pragma' => 'public', 'Cache-Control' => 'public, must-revalidate', - 'Content-Transfer-Encoding' => 'binary', - ]; + 'Content-Transfer-Encoding' => 'binary' + ); $call = $this->opt->getHttpHeaderCallback(); foreach ($headers as $key => $val) { @@ -605,4 +571,32 @@ class ZipStream $this->cdr_ofs = new Bigint(); $this->opt = new ArchiveOptions(); } + + /** + * Is this file larger than large_file_size? + * + * @param string $path + * @return bool + */ + public function isLargeFile(string $path): bool + { + if (!$this->opt->isStatFiles()) { + return false; + } + $stat = stat($path); + return $stat['size'] > $this->opt->getLargeFileSize(); + } + + /** + * Save file attributes for trailing CDR record. + * + * @param File $file + * @return void + */ + public function addToCdr(File $file): void + { + $file->ofs = $this->ofs; + $this->ofs = $this->ofs->add($file->getTotalLength()); + $this->files[] = $file->getCdrFile(); + } } diff --git a/src/vendor/maennchen/zipstream-php/test/BigintTest.php b/src/vendor/maennchen/zipstream-php/test/BigintTest.php index 4d26fcd0b..ac9c7c28b 100644 --- a/src/vendor/maennchen/zipstream-php/test/BigintTest.php +++ b/src/vendor/maennchen/zipstream-php/test/BigintTest.php @@ -1,5 +1,4 @@ at($root)->setContent('bar'); + $file = vfsStream::newFile('foo.txt', 0000)->at($root)->setContent('bar'); $zip = new ZipStream(); $this->expectException(\ZipStream\Exception\FileNotReadableException::class); $zip->addFileFromPath('foo.txt', $file->url()); @@ -50,7 +45,7 @@ class ZipStreamTest extends TestCase public function testDostime(): void { // Allows testing of protected method - $class = new ReflectionClass(File::class); + $class = new \ReflectionClass(File::class); $method = $class->getMethod('dostime'); $method->setAccessible(true); @@ -81,12 +76,81 @@ class ZipStreamTest extends TestCase $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); + $this->assertEquals(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); } + /** + * @return array + */ + protected function getTmpFileStream(): array + { + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + $stream = fopen($tmp, 'wb+'); + + return array($tmp, $stream); + } + + /** + * @param string $tmp + * @return string + */ + protected function validateAndExtractZip($tmp): string + { + $tmpDir = $this->getTmpDir(); + + $zipArch = new \ZipArchive; + $res = $zipArch->open($tmp); + + if ($res !== true) { + $this->fail("Failed to open {$tmp}. Code: $res"); + + return $tmpDir; + } + + $this->assertEquals(0, $zipArch->status); + $this->assertEquals(0, $zipArch->statusSys); + + $zipArch->extractTo($tmpDir); + $zipArch->close(); + + return $tmpDir; + } + + protected function getTmpDir(): string + { + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + unlink($tmp); + mkdir($tmp) or $this->fail('Failed to make directory'); + + return $tmp; + } + + /** + * @param string $path + * @return string[] + */ + protected function getRecursiveFileList(string $path): array + { + $data = array(); + $path = (string)realpath($path); + $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path)); + + $pathLen = strlen($path); + foreach ($files as $file) { + $filePath = $file->getRealPath(); + if (!is_dir($filePath)) { + $data[] = substr($filePath, $pathLen + 1); + } + } + + sort($data); + + return $data; + } + public function testAddFileUtf8NameComment(): void { [$tmp, $stream] = $this->getTmpFileStream(); @@ -113,17 +177,19 @@ class ZipStreamTest extends TestCase $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame([$name], $files); + $this->assertEquals(array($name), $files); $this->assertStringEqualsFile($tmpDir . '/' . $name, $content); - $zipArch = new ZipArchive(); + $zipArch = new \ZipArchive(); $zipArch->open($tmp); - $this->assertSame($comment, $zipArch->getCommentName($name)); + $this->assertEquals($comment, $zipArch->getCommentName($name)); } public function testAddFileUtf8NameNonUtfComment(): void { - [$tmp, $stream] = $this->getTmpFileStream(); + $this->expectException(\ZipStream\Exception\EncodingException::class); + + $stream = $this->getTmpFileStream()[1]; $options = new ArchiveOptions(); $options->setOutputStream($stream); @@ -132,66 +198,33 @@ class ZipStreamTest extends TestCase $name = 'á.txt'; $content = 'any'; - $comment = mb_convert_encoding('á', 'ISO-8859-2', 'UTF-8'); - - // @see https://libzip.org/documentation/zip_file_get_comment.html - // - // mb_convert_encoding hasn't CP437. - // nearly CP850 (DOS-Latin-1) - $guessComment = mb_convert_encoding($comment, 'UTF-8', 'CP850'); + $comment = 'á'; $fileOptions = new FileOptions(); - $fileOptions->setComment($comment); + $fileOptions->setComment(mb_convert_encoding($comment, 'ISO-8859-2', 'UTF-8')); $zip->addFile($name, $content, $fileOptions); - $zip->finish(); - fclose($stream); - - $zipArch = new ZipArchive(); - $zipArch->open($tmp); - $this->assertSame($guessComment, $zipArch->getCommentName($name)); - $this->assertSame($comment, $zipArch->getCommentName($name, ZipArchive::FL_ENC_RAW)); } public function testAddFileNonUtf8NameUtfComment(): void { - [$tmp, $stream] = $this->getTmpFileStream(); + $this->expectException(\ZipStream\Exception\EncodingException::class); + + $stream = $this->getTmpFileStream()[1]; $options = new ArchiveOptions(); $options->setOutputStream($stream); $zip = new ZipStream(null, $options); - $name = mb_convert_encoding('á.txt', 'ISO-8859-2', 'UTF-8'); + $name = 'á.txt'; $content = 'any'; $comment = 'á'; - // @see https://libzip.org/documentation/zip_get_name.html - // - // mb_convert_encoding hasn't CP437. - // nearly CP850 (DOS-Latin-1) - $guessName = mb_convert_encoding($name, 'UTF-8', 'CP850'); - $fileOptions = new FileOptions(); $fileOptions->setComment($comment); - $zip->addFile($name, $content, $fileOptions); - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertNotSame([$name], $files); - $this->assertSame([$guessName], $files); - $this->assertStringEqualsFile($tmpDir . '/' . $guessName, $content); - - $zipArch = new ZipArchive(); - $zipArch->open($tmp); - $this->assertSame($guessName, $zipArch->getNameIndex(0)); - $this->assertSame($name, $zipArch->getNameIndex(0, ZipArchive::FL_ENC_RAW)); - $this->assertSame($comment, $zipArch->getCommentName($guessName)); + $zip->addFile(mb_convert_encoding($name, 'ISO-8859-2', 'UTF-8'), $content, $fileOptions); } public function testAddFileWithStorageMethod(): void @@ -211,13 +244,13 @@ class ZipStreamTest extends TestCase $zip->finish(); fclose($stream); - $zipArch = new ZipArchive(); + $zipArch = new \ZipArchive(); $zipArch->open($tmp); $sample1 = $zipArch->statName('sample.txt'); $sample12 = $zipArch->statName('test/sample.txt'); - $this->assertSame($sample1['comp_method'], Method::STORE); - $this->assertSame($sample12['comp_method'], Method::DEFLATE); + $this->assertEquals($sample1['comp_method'], Method::STORE); + $this->assertEquals($sample12['comp_method'], Method::DEFLATE); $zipArch->close(); } @@ -243,7 +276,7 @@ class ZipStreamTest extends TestCase exec(escapeshellarg(self::OSX_ARCHIVE_UTILITY) . ' ' . escapeshellarg($tmp), $output, $returnStatus); - $this->assertSame(0, $returnStatus); + $this->assertEquals(0, $returnStatus); $this->assertCount(0, $output); $this->assertFileExists(dirname($tmp) . '/' . $folder . '/sample.txt'); @@ -275,7 +308,7 @@ class ZipStreamTest extends TestCase $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); + $this->assertEquals(array('sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'), $files); $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); @@ -306,14 +339,14 @@ class ZipStreamTest extends TestCase $zip->finish(); fclose($stream); - $zipArch = new ZipArchive(); + $zipArch = new \ZipArchive(); $zipArch->open($tmp); $sample1 = $zipArch->statName('sample.txt'); - $this->assertSame(Method::STORE, $sample1['comp_method']); + $this->assertEquals(Method::STORE, $sample1['comp_method']); $sample2 = $zipArch->statName('test/sample.txt'); - $this->assertSame(Method::DEFLATE, $sample2['comp_method']); + $this->assertEquals(Method::DEFLATE, $sample2['comp_method']); $zipArch->close(); } @@ -334,284 +367,6 @@ class ZipStreamTest extends TestCase } } - public function testAddFileFromStream(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - - $zip = new ZipStream(null, $options); - - // In this test we can't use temporary stream to feed data - // because zlib.deflate filter gives empty string before PHP 7 - // it works fine with file stream - $streamExample = fopen(__FILE__, 'rb'); - $zip->addFileFromStream('sample.txt', $streamExample); -// fclose($streamExample); - - $fileOptions = new FileOptions(); - $fileOptions->setMethod(Method::STORE()); - - $streamExample2 = fopen('php://temp', 'wb+'); - fwrite($streamExample2, 'More Simple Sample Data'); - rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2, $fileOptions); -// fclose($streamExample2); - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); - - $this->assertStringEqualsFile(__FILE__, file_get_contents($tmpDir . '/sample.txt')); - $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); - } - - public function testAddFileFromStreamWithStorageMethod(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - - $zip = new ZipStream(null, $options); - - $fileOptions = new FileOptions(); - $fileOptions->setMethod(Method::STORE()); - - $streamExample = fopen('php://temp', 'wb+'); - fwrite($streamExample, 'Sample String Data'); - rewind($streamExample); // move the pointer back to the beginning of file. - $zip->addFileFromStream('sample.txt', $streamExample, $fileOptions); -// fclose($streamExample); - - $streamExample2 = fopen('php://temp', 'bw+'); - fwrite($streamExample2, 'More Simple Sample Data'); - rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2); -// fclose($streamExample2); - - $zip->finish(); - fclose($stream); - - $zipArch = new ZipArchive(); - $zipArch->open($tmp); - - $sample1 = $zipArch->statName('sample.txt'); - $this->assertSame(Method::STORE, $sample1['comp_method']); - - $sample2 = $zipArch->statName('test/sample.txt'); - $this->assertSame(Method::DEFLATE, $sample2['comp_method']); - - $zipArch->close(); - } - - public function testAddFileFromPsr7Stream(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - - $zip = new ZipStream(null, $options); - - $body = 'Sample String Data'; - $response = new Response(200, [], $body); - - $fileOptions = new FileOptions(); - $fileOptions->setMethod(Method::STORE()); - - $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.json'], $files); - $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); - } - - public function testAddFileFromPsr7StreamWithOutputToPsr7Stream(): void - { - [$tmp, $resource] = $this->getTmpFileStream(); - $psr7OutputStream = new Stream($resource); - - $options = new ArchiveOptions(); - $options->setOutputStream($psr7OutputStream); - - $zip = new ZipStream(null, $options); - - $body = 'Sample String Data'; - $response = new Response(200, [], $body); - - $fileOptions = new FileOptions(); - $fileOptions->setMethod(Method::STORE()); - - $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); - $zip->finish(); - $psr7OutputStream->close(); - - $tmpDir = $this->validateAndExtractZip($tmp); - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(['sample.json'], $files); - $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); - } - - public function testAddFileFromPsr7StreamWithFileSizeSet(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - - $zip = new ZipStream(null, $options); - - $body = 'Sample String Data'; - $fileSize = strlen($body); - // Add fake padding - $fakePadding = "\0\0\0\0\0\0"; - $response = new Response(200, [], $body . $fakePadding); - - $fileOptions = new FileOptions(); - $fileOptions->setMethod(Method::STORE()); - $fileOptions->setSize($fileSize); - $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.json'], $files); - $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); - } - - public function testCreateArchiveWithFlushOptionSet(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - $options->setFlushOutput(true); - - $zip = new ZipStream(null, $options); - - $zip->addFile('sample.txt', 'Sample String Data'); - $zip->addFile('test/sample.txt', 'More Simple Sample Data'); - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); - - $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); - $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); - } - - public function testCreateArchiveWithOutputBufferingOffAndFlushOptionSet(): void - { - // WORKAROUND (1/2): remove phpunit's output buffer in order to run test without any buffering - ob_end_flush(); - $this->assertSame(0, ob_get_level()); - - [$tmp, $stream] = $this->getTmpFileStream(); - - $options = new ArchiveOptions(); - $options->setOutputStream($stream); - $options->setFlushOutput(true); - - $zip = new ZipStream(null, $options); - - $zip->addFile('sample.txt', 'Sample String Data'); - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); - - // WORKAROUND (2/2): add back output buffering so that PHPUnit doesn't complain that it is missing - ob_start(); - } - - /** - * @return array - */ - protected function getTmpFileStream(): array - { - $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); - $stream = fopen($tmp, 'wb+'); - - return [$tmp, $stream]; - } - - /** - * @param string $tmp - * @return string - */ - protected function validateAndExtractZip($tmp): string - { - $tmpDir = $this->getTmpDir(); - - $zipArch = new ZipArchive(); - $res = $zipArch->open($tmp); - - if ($res !== true) { - $this->fail("Failed to open {$tmp}. Code: $res"); - - return $tmpDir; - } - - $this->assertSame(0, $zipArch->status); - $this->assertSame(0, $zipArch->statusSys); - - $zipArch->extractTo($tmpDir); - $zipArch->close(); - - return $tmpDir; - } - - protected function getTmpDir(): string - { - $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); - unlink($tmp); - mkdir($tmp) or $this->fail('Failed to make directory'); - - return $tmp; - } - - /** - * @param string $path - * @return string[] - */ - protected function getRecursiveFileList(string $path): array - { - $data = []; - $path = (string)realpath($path); - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - - $pathLen = strlen($path); - foreach ($files as $file) { - $filePath = $file->getRealPath(); - if (!is_dir($filePath)) { - $data[] = substr($filePath, $pathLen + 1); - } - } - - sort($data); - - return $data; - } - protected function addLargeFileFileFromPath($method, $zeroHeader, $zip64): void { [$tmp, $stream] = $this->getTmpFileStream(); @@ -643,8 +398,217 @@ class ZipStreamTest extends TestCase $tmpDir = $this->validateAndExtractZip($tmp); $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt'], $files); + $this->assertEquals(array('sample.txt'), $files); - $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$method}"); + $this->assertEquals(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$method}"); + } + + public function testAddFileFromStream(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + // In this test we can't use temporary stream to feed data + // because zlib.deflate filter gives empty string before PHP 7 + // it works fine with file stream + $streamExample = fopen(__FILE__, 'rb'); + $zip->addFileFromStream('sample.txt', $streamExample); +// fclose($streamExample); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $streamExample2 = fopen('php://temp', 'wb+'); + fwrite($streamExample2, 'More Simple Sample Data'); + rewind($streamExample2); // move the pointer back to the beginning of file. + $zip->addFileFromStream('test/sample.txt', $streamExample2, $fileOptions); +// fclose($streamExample2); + + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + $this->assertEquals(array('sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'), $files); + + $this->assertStringEqualsFile(__FILE__, file_get_contents($tmpDir . '/sample.txt')); + $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); + } + + public function testAddFileFromStreamWithStorageMethod(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $streamExample = fopen('php://temp', 'wb+'); + fwrite($streamExample, 'Sample String Data'); + rewind($streamExample); // move the pointer back to the beginning of file. + $zip->addFileFromStream('sample.txt', $streamExample, $fileOptions); +// fclose($streamExample); + + $streamExample2 = fopen('php://temp', 'bw+'); + fwrite($streamExample2, 'More Simple Sample Data'); + rewind($streamExample2); // move the pointer back to the beginning of file. + $zip->addFileFromStream('test/sample.txt', $streamExample2); +// fclose($streamExample2); + + $zip->finish(); + fclose($stream); + + $zipArch = new \ZipArchive(); + $zipArch->open($tmp); + + $sample1 = $zipArch->statName('sample.txt'); + $this->assertEquals(Method::STORE, $sample1['comp_method']); + + $sample2 = $zipArch->statName('test/sample.txt'); + $this->assertEquals(Method::DEFLATE, $sample2['comp_method']); + + $zipArch->close(); + } + + public function testAddFileFromPsr7Stream(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $body = 'Sample String Data'; + $response = new Response(200, [], $body); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + $this->assertEquals(array('sample.json'), $files); + $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); + } + + public function testAddFileFromPsr7StreamWithOutputToPsr7Stream(): void + { + [$tmp, $resource] = $this->getTmpFileStream(); + $psr7OutputStream = new Stream($resource); + + $options = new ArchiveOptions(); + $options->setOutputStream($psr7OutputStream); + + $zip = new ZipStream(null, $options); + + $body = 'Sample String Data'; + $response = new Response(200, [], $body); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); + $zip->finish(); + $psr7OutputStream->close(); + + $tmpDir = $this->validateAndExtractZip($tmp); + $files = $this->getRecursiveFileList($tmpDir); + + $this->assertEquals(array('sample.json'), $files); + $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); + } + + public function testAddFileFromPsr7StreamWithFileSizeSet(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $body = 'Sample String Data'; + $fileSize = strlen($body); + // Add fake padding + $fakePadding = "\0\0\0\0\0\0"; + $response = new Response(200, [], $body . $fakePadding); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + $fileOptions->setSize($fileSize); + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + $this->assertEquals(array('sample.json'), $files); + $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); + } + + public function testCreateArchiveWithFlushOptionSet(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); + + $zip->addFile('sample.txt', 'Sample String Data'); + $zip->addFile('test/sample.txt', 'More Simple Sample Data'); + + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + $this->assertEquals(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files); + + $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); + $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); + } + + public function testCreateArchiveWithOutputBufferingOffAndFlushOptionSet(): void + { + // WORKAROUND (1/2): remove phpunit's output buffer in order to run test without any buffering + ob_end_flush(); + $this->assertEquals(0, ob_get_level()); + + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); + + $zip->addFile('sample.txt', 'Sample String Data'); + + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data'); + + // WORKAROUND (2/2): add back output buffering so that PHPUnit doesn't complain that it is missing + ob_start(); } } diff --git a/src/vendor/maennchen/zipstream-php/test/bootstrap.php b/src/vendor/maennchen/zipstream-php/test/bootstrap.php index 13c7a0e6c..b43c9bd6c 100644 --- a/src/vendor/maennchen/zipstream-php/test/bootstrap.php +++ b/src/vendor/maennchen/zipstream-php/test/bootstrap.php @@ -1,5 +1,4 @@ getReal() - $invsqrt->getImaginary(), $complex->getImaginary() + $invsqrt->getReal() @@ -52,9 +56,6 @@ class Functions /** * Returns the inverse hyperbolic cosine of a complex number. * - * Formula from Wolfram Alpha: - * cosh^(-1)z = ln(z + sqrt(z + 1) sqrt(z - 1)). - * * @param Complex|mixed $complex Complex number or a numeric value. * @return Complex The inverse hyperbolic cosine of the complex argument. * @throws Exception If argument isn't a valid real or complex number. @@ -67,15 +68,11 @@ class Functions return new Complex(\acosh($complex->getReal())); } - $acosh = self::ln( - Operations::add( - $complex, - Operations::multiply( - self::sqrt(Operations::add($complex, 1)), - self::sqrt(Operations::subtract($complex, 1)) - ) - ) - ); + $acosh = self::acos($complex) + ->reverse(); + if ($acosh->getReal() < 0.0) { + $acosh = $acosh->invertReal(); + } return $acosh; } @@ -215,7 +212,10 @@ class Functions { $complex = Complex::validateComplexArgument($complex); - $invsqrt = self::sqrt(Operations::subtract(1, Operations::multiply($complex, $complex))); + $square = Operations::multiply($complex, $complex); + $invsqrt = new Complex(1.0); + $invsqrt = Operations::subtract($invsqrt, $square); + $invsqrt = self::sqrt($invsqrt); $adjust = new Complex( $invsqrt->getReal() - $complex->getImaginary(), $invsqrt->getImaginary() + $complex->getReal() @@ -277,21 +277,9 @@ class Functions $uResult = $d1Value->divideBy($d2Value); $uResult = self::ln($uResult); - $realMultiplier = -0.5; - $imaginaryMultiplier = 0.5; - - if (abs($uResult->getImaginary()) === M_PI) { - // If we have an imaginary value at the max or min (PI or -PI), then we need to ensure - // that the primary is assigned for the correct quadrant. - $realMultiplier = ( - ($uResult->getImaginary() === M_PI && $uResult->getReal() > 0.0) || - ($uResult->getImaginary() === -M_PI && $uResult->getReal() < 0.0) - ) ? 0.5 : -0.5; - } - return new Complex( - $uResult->getImaginary() * $realMultiplier, - $uResult->getReal() * $imaginaryMultiplier, + (($uResult->getImaginary() == M_PI) ? -M_PI : $uResult->getImaginary()) * -0.5, + $uResult->getReal() * 0.5, $complex->getSuffix() ); } @@ -299,9 +287,6 @@ class Functions /** * Returns the inverse hyperbolic tangent of a complex number. * - * Formula from Wolfram Alpha: - * tanh^(-1)z = 1/2 [ln(1 + z) - ln(1 - z)]. - * * @param Complex|mixed $complex Complex number or a numeric value. * @return Complex The inverse hyperbolic tangent of the complex argument. * @throws Exception If argument isn't a valid real or complex number. @@ -319,15 +304,12 @@ class Functions } } - $atanh = Operations::multiply( - Operations::subtract( - self::ln(Operations::add(1.0, $complex)), - self::ln(Operations::subtract(1.0, $complex)) - ), - 0.5 - ); - - return $atanh; + $iComplex = clone $complex; + $iComplex = $iComplex->invertImaginary() + ->reverse(); + return self::atan($iComplex) + ->invertReal() + ->reverse(); } /** diff --git a/src/vendor/markbaker/complex/composer.json b/src/vendor/markbaker/complex/composer.json index 246683ca4..ea1d06f56 100644 --- a/src/vendor/markbaker/complex/composer.json +++ b/src/vendor/markbaker/complex/composer.json @@ -11,21 +11,14 @@ "email": "mark@lange.demon.co.uk" } ], - "config": { - "sort-packages": true, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "markbaker/ukraine": true - } - }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.7", - "phpcompatibility/php-compatibility": "^9.3", - "dealerdirect/phpcodesniffer-composer-installer": "dev-master" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", + "squizlabs/php_codesniffer": "^3.4", + "phpcompatibility/php-compatibility": "^9.0", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0" }, "autoload": { "psr-4": { diff --git a/src/vendor/markbaker/matrix/.github/workflows/main.yaml b/src/vendor/markbaker/matrix/.github/workflows/main.yaml index 5fa1bdb2d..158fcdfc6 100644 --- a/src/vendor/markbaker/matrix/.github/workflows/main.yaml +++ b/src/vendor/markbaker/matrix/.github/workflows/main.yaml @@ -12,17 +12,12 @@ jobs: - '7.4' - '8.0' - '8.1' - - '8.2' - - include: - - php-version: 'nightly' - experimental: true name: PHP ${{ matrix.php-version }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v2 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -36,21 +31,20 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Delete composer lock file + - name: Set composer flags id: composer-lock - if: ${{ matrix.php-version == '8.0' || matrix.php-version == '8.1' || matrix.php-version == '8.2' || matrix.php-version == 'nightly' }} + if: ${{ matrix.php-version == '8.0' || matrix.php-version == '8.1' }} run: | - rm composer.lock echo "::set-output name=flags::--ignore-platform-reqs" - name: Install dependencies - run: composer update --no-progress --prefer-dist --optimize-autoloader ${{ steps.composer-lock.outputs.flags }} + run: composer install --no-progress --prefer-dist --optimize-autoloader ${{ steps.composer-lock.outputs.flags }} - name: Setup problem matchers for PHP run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" @@ -65,7 +59,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v2 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -80,7 +74,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -96,7 +90,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v2 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 @@ -110,7 +104,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} diff --git a/src/vendor/markbaker/matrix/composer.json b/src/vendor/markbaker/matrix/composer.json index e86a1e055..fa90f5639 100644 --- a/src/vendor/markbaker/matrix/composer.json +++ b/src/vendor/markbaker/matrix/composer.json @@ -15,14 +15,14 @@ "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", "phpdocumentor/phpdocumentor": "2.*", "phpmd/phpmd": "2.*", "sebastian/phpcpd": "^4.0", "phploc/phploc": "^4.0", - "squizlabs/php_codesniffer": "^3.7", - "phpcompatibility/php-compatibility": "^9.3", - "dealerdirect/phpcodesniffer-composer-installer": "dev-master" + "squizlabs/php_codesniffer": "^3.4", + "phpcompatibility/php-compatibility": "^9.0", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0" }, "autoload": { "psr-4": { @@ -43,10 +43,5 @@ "versions": "phpcs --report-width=200 --standard=PHPCompatibility --report=summary,full classes/src/ --runtime-set testVersion 7.2- -n", "coverage": "phpunit -c phpunit.xml.dist --coverage-text --coverage-html ./build/coverage" }, - "minimum-stability": "dev", - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - } -} + "minimum-stability": "dev" +} \ No newline at end of file diff --git a/src/vendor/monolog/monolog/CHANGELOG.md b/src/vendor/monolog/monolog/CHANGELOG.md index 122d85cde..e374fa78e 100644 --- a/src/vendor/monolog/monolog/CHANGELOG.md +++ b/src/vendor/monolog/monolog/CHANGELOG.md @@ -1,58 +1,3 @@ -### 2.10.0 (2024-11-12) - - * Added `$fileOpenMode` to `StreamHandler` to define a custom fopen mode to open the log file (#1913) - * Fixed `StreamHandler` handling of write failures so that it now closes/reopens the stream and retries the write once before failing (#1882) - * Fixed `StreamHandler` error handler causing issues if a stream handler triggers an error (#1866) - * Fixed `JsonFormatter` handling of incomplete classes (#1834) - * Fixed `RotatingFileHandler` bug where rotation could sometimes not happen correctly (#1905) - -### 2.9.3 (2024-04-12) - - * Fixed PHP 8.4 deprecation warnings (#1874) - -### 2.9.2 (2023-10-27) - - * Fixed display_errors parsing in ErrorHandler which did not support string values (#1804) - * Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815) - * Fixed normalization error when normalizing incomplete classes (#1833) - -### 2.9.1 (2023-02-06) - - * Fixed Logger not being serializable anymore (#1792) - -### 2.9.0 (2023-02-05) - - * Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748) - * Added support for enum context values in PsrLogMessageProcessor (#1773) - * Added graylog2/gelf-php 2.x support (#1747) - * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739) - * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791) - * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758) - * Fixed infinite loop detection within Fibers (#1753) - * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781) - -### 2.8.0 (2022-07-24) - - * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734) - * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723) - * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733) - * Added `GoogleCloudLoggingFormatter` (#1719) - * Added support for Predis 2.x (#1732) - * Added `AmqpHandler->setExtraAttributes` to allow configuring attributes when using an AMQPExchange (#1724) - * Fixed serialization/unserialization of handlers to make sure private properties are included (#1727) - * Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing `\n` or `\r` sequences (#1720) - * Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726) - * Fixed PHP 8.2 deprecation warnings (#1722) - * Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678) - -### 2.7.0 (2022-06-09) - - * Added `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682) - * Added `Logger::useLoggingLoopDetection` to allow disabling cyclic logging detection in concurrent frameworks (#1681) - * Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670) - * Marked the reusable `Monolog\Test\TestCase` class as `@internal` to make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677) - * Fixed RotatingFileHandler issue when the date format contained slashes (#1671) - ### 2.6.0 (2022-05-10) * Deprecated `SwiftMailerHandler`, use `SymfonyMailerHandler` instead diff --git a/src/vendor/monolog/monolog/composer.json b/src/vendor/monolog/monolog/composer.json index a1f08a22d..52cb35f67 100644 --- a/src/vendor/monolog/monolog/composer.json +++ b/src/vendor/monolog/monolog/composer.json @@ -21,15 +21,16 @@ "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.3", "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.38 || ^9.6.19", - "predis/predis": "^1.1 || ^2.0", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1", "rollbar/rollbar": "^1.3 || ^2 || ^3", "ruflin/elastica": "^7", "swiftmailer/swiftmailer": "^5.3|^6.0", @@ -47,6 +48,7 @@ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "rollbar/rollbar": "Allow sending log messages to Rollbar", + "php-console/php-console": "Allow sending log messages to Google Chrome", "ext-mbstring": "Allow to work properly with unicode symbols", "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", diff --git a/src/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php b/src/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php index 789f9bfc4..6a1ba9b25 100644 --- a/src/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php +++ b/src/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php @@ -30,8 +30,6 @@ class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable { $this->useMicroseconds = $useMicroseconds; - // if you like to use a custom time to pass to Logger::addRecord directly, - // call modify() or setTimestamp() on this instance to change the date after creating it parent::__construct('now', $timezone); } diff --git a/src/vendor/monolog/monolog/src/Monolog/ErrorHandler.php b/src/vendor/monolog/monolog/src/Monolog/ErrorHandler.php index 1406d34e8..16794be65 100644 --- a/src/vendor/monolog/monolog/src/Monolog/ErrorHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/ErrorHandler.php @@ -46,8 +46,8 @@ class ErrorHandler private $fatalLevel = LogLevel::ALERT; /** @var ?string */ private $reservedMemory = null; - /** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */ - private $lastFatalData = null; + /** @var ?mixed */ + private $lastFatalTrace; /** @var int[] */ private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; @@ -198,7 +198,7 @@ class ErrorHandler ($this->previousExceptionHandler)($e); } - if (!headers_sent() && in_array(strtolower((string) ini_get('display_errors')), ['0', '', 'false', 'off', 'none', 'no'], true)) { + if (!headers_sent() && !ini_get('display_errors')) { http_response_code(500); } @@ -223,7 +223,7 @@ class ErrorHandler } else { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); array_shift($trace); // Exclude handleError from trace - $this->lastFatalData = ['type' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $trace]; + $this->lastFatalTrace = $trace; } if ($this->previousErrorHandler === true) { @@ -242,18 +242,12 @@ class ErrorHandler { $this->reservedMemory = ''; - if (is_array($this->lastFatalData)) { - $lastError = $this->lastFatalData; - } else { - $lastError = error_get_last(); - } - + $lastError = error_get_last(); if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { - $trace = $lastError['trace'] ?? null; $this->logger->log( $this->fatalLevel, 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], - ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $trace] + ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace] ); if ($this->logger instanceof Logger) { diff --git a/src/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/src/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php index 867ae586b..41b56b3c0 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php +++ b/src/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php @@ -15,7 +15,6 @@ namespace Monolog\Formatter; * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler - * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockFormatter implements FormatterInterface { diff --git a/src/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/src/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php index 3b3e1e7f6..a1a79372d 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/src/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -47,11 +47,6 @@ class GelfMessageFormatter extends NormalizerFormatter */ protected $maxLength; - /** - * @var int - */ - private $gelfVersion = 2; - /** * Translates Monolog log levels to Graylog2 log priorities. * @@ -83,10 +78,6 @@ class GelfMessageFormatter extends NormalizerFormatter $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; - - if (method_exists(Message::class, 'setFacility')) { - $this->gelfVersion = 1; - } } /** @@ -122,20 +113,16 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } - if ($this->gelfVersion === 1) { - if (isset($record['channel'])) { - $message->setFacility($record['channel']); - } - if (isset($extra['line'])) { - $message->setLine($extra['line']); - unset($extra['line']); - } - if (isset($extra['file'])) { - $message->setFile($extra['file']); - unset($extra['file']); - } - } else { - $message->setAdditional('facility', $record['channel']); + if (isset($record['channel'])) { + $message->setFacility($record['channel']); + } + if (isset($extra['line'])) { + $message->setLine($extra['line']); + unset($extra['line']); + } + if (isset($extra['file'])) { + $message->setFile($extra['file']); + unset($extra['file']); } foreach ($extra as $key => $val) { @@ -160,13 +147,11 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setAdditional($this->contextPrefix . $key, $val); } - if ($this->gelfVersion === 1) { - /** @phpstan-ignore-next-line */ - if (null === $message->getFile() && isset($context['exception']['file'])) { - if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { - $message->setFile($matches[1]); - $message->setLine($matches[2]); - } + /** @phpstan-ignore-next-line */ + if (null === $message->getFile() && isset($context['exception']['file'])) { + if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { + $message->setFile($matches[1]); + $message->setLine($matches[2]); } } diff --git a/src/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/src/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php index 753e6852c..42735a6b4 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +++ b/src/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -178,29 +178,12 @@ class JsonFormatter extends NormalizerFormatter return $normalized; } - if (is_object($data)) { - if ($data instanceof \DateTimeInterface) { - return $this->formatDate($data); - } + if ($data instanceof \DateTimeInterface) { + return $this->formatDate($data); + } - if ($data instanceof Throwable) { - return $this->normalizeException($data, $depth); - } - - // if the object has specific json serializability we want to make sure we skip the __toString treatment below - if ($data instanceof \JsonSerializable) { - return $data; - } - - if (\get_class($data) === '__PHP_Incomplete_Class') { - return new \ArrayObject($data); - } - - if (method_exists($data, '__toString')) { - return $data->__toString(); - } - - return $data; + if ($data instanceof Throwable) { + return $this->normalizeException($data, $depth); } if (is_resource($data)) { diff --git a/src/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/src/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php index e6e789833..d0b4de94a 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +++ b/src/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -153,12 +153,6 @@ class LineFormatter extends NormalizerFormatter if ($previous = $e->getPrevious()) { do { - $depth++; - if ($depth > $this->maxNormalizeDepth) { - $str .= "\n[previous exception] Over " . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; - break; - } - $str .= "\n[previous exception] " . $this->formatException($previous); } while ($previous = $previous->getPrevious()); } @@ -186,11 +180,7 @@ class LineFormatter extends NormalizerFormatter { if ($this->allowInlineLineBreaks) { if (0 === strpos($str, '{')) { - $str = preg_replace('/(? $value */ $value = $data->jsonSerialize(); - } elseif (\get_class($data) === '__PHP_Incomplete_Class') { - $accessor = new \ArrayObject($data); - $value = (string) $accessor['__PHP_Incomplete_Class_Name']; } elseif (method_exists($data, '__toString')) { /** @var string $value */ $value = $data->__toString(); @@ -201,10 +198,6 @@ class NormalizerFormatter implements FormatterInterface */ protected function normalizeException(Throwable $e, int $depth = 0) { - if ($depth > $this->maxNormalizeDepth) { - return ['Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization']; - } - if ($e instanceof \JsonSerializable) { return (array) $e->jsonSerialize(); } diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php index 994872ce8..e30d784dd 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php @@ -27,31 +27,6 @@ class AmqpHandler extends AbstractProcessingHandler * @var AMQPExchange|AMQPChannel $exchange */ protected $exchange; - /** @var array */ - private $extraAttributes = []; - - /** - * @return array - */ - public function getExtraAttributes(): array - { - return $this->extraAttributes; - } - - /** - * Configure extra attributes to pass to the AMQPExchange (if you are using the amqp extension) - * - * @param array $extraAttributes One of content_type, content_encoding, - * message_id, user_id, app_id, delivery_mode, - * priority, timestamp, expiration, type - * or reply_to, headers. - * @return AmqpHandler - */ - public function setExtraAttributes(array $extraAttributes): self - { - $this->extraAttributes = $extraAttributes; - return $this; - } /** * @var string @@ -85,18 +60,14 @@ class AmqpHandler extends AbstractProcessingHandler $routingKey = $this->getRoutingKey($record); if ($this->exchange instanceof AMQPExchange) { - $attributes = [ - 'delivery_mode' => 2, - 'content_type' => 'application/json', - ]; - if ($this->extraAttributes) { - $attributes = array_merge($attributes, $this->extraAttributes); - } $this->exchange->publish( $data, $routingKey, 0, - $attributes + [ + 'delivery_mode' => 2, + 'content_type' => 'application/json', + ] ); } else { $this->exchange->basic_publish( @@ -151,14 +122,13 @@ class AmqpHandler extends AbstractProcessingHandler private function createAmqpMessage(string $data): AMQPMessage { - $attributes = [ - 'delivery_mode' => 2, - 'content_type' => 'application/json', - ]; - if ($this->extraAttributes) { - $attributes = array_merge($attributes, $this->extraAttributes); - } - return new AMQPMessage($data, $attributes); + return new AMQPMessage( + $data, + [ + 'delivery_mode' => 2, + 'content_type' => 'application/json', + ] + ); } /** diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php index 95bbfed42..fa383f1c2 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -14,7 +14,6 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Utils; -use Monolog\Logger; use function count; use function headers_list; @@ -178,7 +177,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler $extra = static::dump('Extra', $record['extra']); if (empty($context) && empty($extra)) { - $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted'])); + $script[] = static::call_array('log', static::handleStyles($record['formatted'])); } else { $script = array_merge( $script, @@ -193,20 +192,6 @@ class BrowserConsoleHandler extends AbstractProcessingHandler return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; } - private static function getConsoleMethodForLevel(int $level): string - { - return [ - Logger::DEBUG => 'debug', - Logger::INFO => 'info', - Logger::NOTICE => 'info', - Logger::WARNING => 'warn', - Logger::ERROR => 'error', - Logger::CRITICAL => 'error', - Logger::ALERT => 'error', - Logger::EMERGENCY => 'error', - ][$level] ?? 'log'; - } - /** * @return string[] */ diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php index 234ecf614..d1a98b8fe 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -149,7 +149,7 @@ class ChromePHPHandler extends AbstractProcessingHandler } $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); - $data = base64_encode($json); + $data = base64_encode(utf8_encode($json)); if (strlen($data) > 3 * 1024) { self::$overflowed = true; @@ -163,8 +163,8 @@ class ChromePHPHandler extends AbstractProcessingHandler 'extra' => [], ]; self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); - $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); - $data = base64_encode($json); + $json = Utils::jsonEncode(self::$json, null, true); + $data = base64_encode(utf8_encode($json)); } if (trim($data) !== '') { diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php index 3535a4fcd..fc8f58f1a 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -17,9 +17,8 @@ use Monolog\Utils; /** * Logs to Cube. * - * @link https://github.com/square/cube/wiki + * @link http://square.github.com/cube/ * @author Wan Chen - * @deprecated Since 2.8.0 and 3.2.0, Cube appears abandoned and thus we will drop this handler in Monolog 4 */ class CubeHandler extends AbstractProcessingHandler { diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php index 264b380d7..e88375c0e 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php @@ -187,7 +187,6 @@ class ElasticsearchHandler extends AbstractProcessingHandler */ protected function createExceptionFromResponses($responses): Throwable { - // @phpstan-ignore offsetAccess.nonOffsetAccessible foreach ($responses['items'] ?? [] as $item) { if (isset($item['index']['error'])) { return $this->createExceptionFromError($item['index']['error']); diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php index 5e43e1dc2..718f17ef1 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php @@ -161,7 +161,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese * * @phpstan-param Record $record */ - public function getHandler(?array $record = null) + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php index dfcb3af28..0627b4451 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -210,7 +210,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa * * @phpstan-param Record $record */ - public function getHandler(?array $record = null) + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php index 5715d5800..b837bdb66 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -28,7 +28,6 @@ use Monolog\Formatter\FormatterInterface; * @see https://www.flowdock.com/api/push * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler - * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockHandler extends SocketHandler { diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/Handler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/Handler.php index 34b4935dd..afef2fd74 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/Handler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/Handler.php @@ -48,15 +48,6 @@ abstract class Handler implements HandlerInterface { $this->close(); - $reflClass = new \ReflectionClass($this); - - $keys = []; - foreach ($reflClass->getProperties() as $reflProp) { - if (!$reflProp->isStatic()) { - $keys[] = $reflProp->getName(); - } - } - - return $keys; + return array_keys(get_object_vars($this)); } } diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php index 23a1d1178..6e209b190 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php @@ -25,7 +25,7 @@ use PhpConsole\Helper; * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely * * Usage: - * 1. Install Google Chrome extension [now dead and removed from the chrome store] + * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef * 2. See overview https://github.com/barbushin/php-console#overview * 3. Install PHP Console library https://github.com/barbushin/php-console#installation * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png) @@ -39,7 +39,6 @@ use PhpConsole\Helper; * @author Sergey Barbushin https://www.linkedin.com/in/barbushin * * @phpstan-import-type Record from \Monolog\Logger - * @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4 */ class PHPConsoleHandler extends AbstractProcessingHandler { diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php index 91d16eaf6..938eee6b2 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -30,7 +30,7 @@ use Monolog\Logger; */ class RedisHandler extends AbstractProcessingHandler { - /** @var \Predis\Client<\Predis\Client>|\Redis */ + /** @var \Predis\Client|\Redis */ private $redisClient; /** @var string */ private $redisKey; @@ -38,7 +38,7 @@ class RedisHandler extends AbstractProcessingHandler protected $capSize; /** - * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param \Predis\Client|\Redis $redis The redis instance * @param string $key The key name to push records to * @param int $capSize Number of entries to limit list size to, 0 = unlimited */ diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php index 7789309c1..f9fede8ee 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php @@ -28,13 +28,13 @@ use Monolog\Logger; */ class RedisPubSubHandler extends AbstractProcessingHandler { - /** @var \Predis\Client<\Predis\Client>|\Redis */ + /** @var \Predis\Client|\Redis */ private $redisClient; /** @var string */ private $channelKey; /** - * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param \Predis\Client|\Redis $redis The redis instance * @param string $key The channel key to publish records to */ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true) diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php index 2d0c1a72d..2b7c48030 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -112,22 +112,17 @@ class RotatingFileHandler extends StreamHandler */ protected function write(array $record): void { - // on the first record written, if the log is new, we rotate (once per day) after the log has been written so that the new file exists + // on the first record written, if the log is new, we should rotate (once per day) if (null === $this->mustRotate) { $this->mustRotate = null === $this->url || !file_exists($this->url); } - // if the next rotation is expired, then we rotate immediately if ($this->nextRotation <= $record['datetime']) { $this->mustRotate = true; - $this->close(); // triggers rotation + $this->close(); } parent::write($record); - - if ($this->mustRotate) { - $this->close(); // triggers rotation - } } /** @@ -139,8 +134,6 @@ class RotatingFileHandler extends StreamHandler $this->url = $this->getTimedFilename(); $this->nextRotation = new \DateTimeImmutable('tomorrow'); - $this->mustRotate = false; - // skip GC of old logs if files are unlimited if (0 === $this->maxFiles) { return; @@ -173,6 +166,8 @@ class RotatingFileHandler extends StreamHandler restore_error_handler(); } } + + $this->mustRotate = false; } protected function getTimedFilename(): string @@ -196,11 +191,7 @@ class RotatingFileHandler extends StreamHandler $fileInfo = pathinfo($this->filename); $glob = str_replace( ['{filename}', '{date}'], - [$fileInfo['filename'], str_replace( - ['Y', 'y', 'm', 'd'], - ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'], - $this->dateFormat) - ], + [$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'], $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (isset($fileInfo['extension'])) { diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php index 25cce07f9..c128a32d1 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -90,7 +90,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter * * @return HandlerInterface */ - public function getHandler(?array $record = null) + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php b/src/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php index 9ae100371..71a410946 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php @@ -100,7 +100,7 @@ class SlackRecord bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array(), - ?FormatterInterface $formatter = null + FormatterInterface $formatter = null ) { $this ->setChannel($channel) diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php index 218d43847..e6c795699 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -41,22 +41,17 @@ class StreamHandler extends AbstractProcessingHandler protected $filePermission; /** @var bool */ protected $useLocking; - /** @var string */ - protected $fileOpenMode; /** @var true|null */ private $dirCreated = null; - /** @var bool */ - private $retrying = false; /** * @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) * @param bool $useLocking Try to lock log file before doing any writes - * @param string $fileOpenMode The fopen() mode used when opening a file, if $stream is a file path * * @throws \InvalidArgumentException If stream is not a resource or string */ - public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false, $fileOpenMode = 'a') + public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) { parent::__construct($level, $bubble); @@ -83,7 +78,6 @@ class StreamHandler extends AbstractProcessingHandler throw new \InvalidArgumentException('A stream must either be a resource or a string.'); } - $this->fileOpenMode = $fileOpenMode; $this->filePermission = $filePermission; $this->useLocking = $useLocking; } @@ -140,17 +134,12 @@ class StreamHandler extends AbstractProcessingHandler } $this->createDir($url); $this->errorMessage = null; - set_error_handler(function (...$args) { - return $this->customErrorHandler(...$args); - }); - try { - $stream = fopen($url, $this->fileOpenMode); - if ($this->filePermission !== null) { - @chmod($url, $this->filePermission); - } - } finally { - restore_error_handler(); + set_error_handler([$this, 'customErrorHandler']); + $stream = fopen($url, 'a'); + if ($this->filePermission !== null) { + @chmod($url, $this->filePermission); } + restore_error_handler(); if (!is_resource($stream)) { $this->stream = null; @@ -170,30 +159,8 @@ class StreamHandler extends AbstractProcessingHandler flock($stream, LOCK_EX); } - $this->errorMessage = null; - set_error_handler(function (...$args) { - return $this->customErrorHandler(...$args); - }); - try { - $this->streamWrite($stream, $record); - } finally { - restore_error_handler(); - } - if ($this->errorMessage !== null) { - $error = $this->errorMessage; - // close the resource if possible to reopen it, and retry the failed write - if (!$this->retrying && $this->url !== null && $this->url !== 'php://memory') { - $this->retrying = true; - $this->close(); - $this->write($record); + $this->streamWrite($stream, $record); - return; - } - - throw new \UnexpectedValueException('Writing to the log file failed: '.$error . Utils::getRecordMessageForException($record)); - } - - $this->retrying = false; if ($this->useLocking) { flock($stream, LOCK_UN); } @@ -213,7 +180,7 @@ class StreamHandler extends AbstractProcessingHandler private function customErrorHandler(int $code, string $msg): bool { - $this->errorMessage = preg_replace('{^(fopen|mkdir|fwrite)\(.*?\): }', '', $msg); + $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg); return true; } @@ -242,12 +209,10 @@ class StreamHandler extends AbstractProcessingHandler $dir = $this->getDirFromStream($url); if (null !== $dir && !is_dir($dir)) { $this->errorMessage = null; - set_error_handler(function (...$args) { - return $this->customErrorHandler(...$args); - }); + set_error_handler([$this, 'customErrorHandler']); $status = mkdir($dir, 0777, true); restore_error_handler(); - if (false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === false) { + if (false === $status && !is_dir($dir)) { throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: '.$this->errorMessage, $dir)); } } diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php index a6223b795..8912eba51 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php @@ -108,9 +108,9 @@ class TelegramBotHandler extends AbstractProcessingHandler string $channel, $level = Logger::DEBUG, bool $bubble = true, - ?string $parseMode = null, - ?bool $disableWebPagePreview = null, - ?bool $disableNotification = null, + string $parseMode = null, + bool $disableWebPagePreview = null, + bool $disableNotification = null, bool $splitLongMessages = false, bool $delayBetweenMessages = false ) @@ -130,7 +130,7 @@ class TelegramBotHandler extends AbstractProcessingHandler $this->delayBetweenMessages($delayBetweenMessages); } - public function setParseMode(?string $parseMode = null): self + public function setParseMode(string $parseMode = null): self { if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) { throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.'); @@ -141,14 +141,14 @@ class TelegramBotHandler extends AbstractProcessingHandler return $this; } - public function disableWebPagePreview(?bool $disableWebPagePreview = null): self + public function disableWebPagePreview(bool $disableWebPagePreview = null): self { $this->disableWebPagePreview = $disableWebPagePreview; return $this; } - public function disableNotification(?bool $disableNotification = null): self + public function disableNotification(bool $disableNotification = null): self { $this->disableNotification = $disableNotification; diff --git a/src/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/src/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php index b6d3d3b19..2dd136720 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php +++ b/src/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -64,18 +64,4 @@ class WhatFailureGroupHandler extends GroupHandler } } } - - /** - * {@inheritDoc} - */ - public function close(): void - { - foreach ($this->handlers as $handler) { - try { - $handler->close(); - } catch (\Throwable $e) { - // What failure? - } - } - } } diff --git a/src/vendor/monolog/monolog/src/Monolog/Logger.php b/src/vendor/monolog/monolog/src/Monolog/Logger.php index bf65d3c53..0c2240e27 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Logger.php +++ b/src/vendor/monolog/monolog/src/Monolog/Logger.php @@ -111,22 +111,6 @@ class Logger implements LoggerInterface, ResettableInterface self::EMERGENCY => 'EMERGENCY', ]; - /** - * Mapping between levels numbers defined in RFC 5424 and Monolog ones - * - * @phpstan-var array $rfc_5424_levels - */ - private const RFC_5424_LEVELS = [ - 7 => self::DEBUG, - 6 => self::INFO, - 5 => self::NOTICE, - 4 => self::WARNING, - 3 => self::ERROR, - 2 => self::CRITICAL, - 1 => self::ALERT, - 0 => self::EMERGENCY, - ]; - /** * @var string */ @@ -168,18 +152,6 @@ class Logger implements LoggerInterface, ResettableInterface */ private $logDepth = 0; - /** - * @var \WeakMap<\Fiber, int> Keeps track of depth inside fibers to prevent infinite logging loops - */ - private $fiberLogDepth; - - /** - * @var bool Whether to detect infinite logging loops - * - * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this - */ - private $detectCycles = true; - /** * @psalm-param array $processors * @@ -194,13 +166,6 @@ class Logger implements LoggerInterface, ResettableInterface $this->setHandlers($handlers); $this->processors = $processors; $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC'); - - if (\PHP_VERSION_ID >= 80100) { - // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 - /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ - $fiberLogDepth = new \WeakMap(); - $this->fiberLogDepth = $fiberLogDepth; - } } public function getName(): string @@ -319,46 +284,23 @@ class Logger implements LoggerInterface, ResettableInterface return $this; } - public function useLoggingLoopDetection(bool $detectCycles): self - { - $this->detectCycles = $detectCycles; - - return $this; - } - /** * Adds a log record. * - * @param int $level The logging level (a Monolog or RFC 5424 level) - * @param string $message The log message - * @param mixed[] $context The log context - * @param DateTimeImmutable $datetime Optional log date to log into the past or future - * @return bool Whether the record has been processed + * @param int $level The logging level + * @param string $message The log message + * @param mixed[] $context The log context + * @return bool Whether the record has been processed * * @phpstan-param Level $level */ - public function addRecord(int $level, string $message, array $context = [], ?DateTimeImmutable $datetime = null): bool + public function addRecord(int $level, string $message, array $context = []): bool { - if (isset(self::RFC_5424_LEVELS[$level])) { - $level = self::RFC_5424_LEVELS[$level]; - } - - if ($this->detectCycles) { - if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) { - // @phpstan-ignore offsetAssign.dimType - $this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0; - $logDepth = ++$this->fiberLogDepth[$fiber]; - } else { - $logDepth = ++$this->logDepth; - } - } else { - $logDepth = 0; - } - - if ($logDepth === 3) { + $this->logDepth += 1; + if ($this->logDepth === 3) { $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.'); return false; - } elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above + } elseif ($this->logDepth >= 5) { // log depth 4 is let through so we can log the warning above return false; } @@ -380,7 +322,7 @@ class Logger implements LoggerInterface, ResettableInterface 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, - 'datetime' => $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), + 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), 'extra' => [], ]; @@ -407,13 +349,7 @@ class Logger implements LoggerInterface, ResettableInterface } } } finally { - if ($this->detectCycles) { - if (isset($fiber)) { - $this->fiberLogDepth[$fiber]--; - } else { - $this->logDepth--; - } - } + $this->logDepth--; } return null !== $record; @@ -565,7 +501,7 @@ class Logger implements LoggerInterface, ResettableInterface * * This method allows for compatibility with common interfaces. * - * @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level) + * @param mixed $level The log level * @param string|Stringable $message The log message * @param mixed[] $context The log context * @@ -577,10 +513,6 @@ class Logger implements LoggerInterface, ResettableInterface throw new \InvalidArgumentException('$level is expected to be a string or int'); } - if (isset(self::RFC_5424_LEVELS[$level])) { - $level = self::RFC_5424_LEVELS[$level]; - } - $level = static::toMonologLevel($level); $this->addRecord($level, (string) $message, $context); @@ -723,40 +655,4 @@ class Logger implements LoggerInterface, ResettableInterface ($this->exceptionHandler)($e, $record); } - - /** - * @return array - */ - public function __serialize(): array - { - return [ - 'name' => $this->name, - 'handlers' => $this->handlers, - 'processors' => $this->processors, - 'microsecondTimestamps' => $this->microsecondTimestamps, - 'timezone' => $this->timezone, - 'exceptionHandler' => $this->exceptionHandler, - 'logDepth' => $this->logDepth, - 'detectCycles' => $this->detectCycles, - ]; - } - - /** - * @param array $data - */ - public function __unserialize(array $data): void - { - foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) { - if (isset($data[$property])) { - $this->$property = $data[$property]; - } - } - - if (\PHP_VERSION_ID >= 80100) { - // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 - /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ - $fiberLogDepth = new \WeakMap(); - $this->fiberLogDepth = $fiberLogDepth; - } - } } diff --git a/src/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/src/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php index e7c12176a..2c2a00e75 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php +++ b/src/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -66,8 +66,6 @@ class PsrLogMessageProcessor implements ProcessorInterface } else { $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE); } - } elseif ($val instanceof \UnitEnum) { - $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name; } elseif (is_object($val)) { $replacements[$placeholder] = '[object '.Utils::getClass($val).']'; } elseif (is_array($val)) { diff --git a/src/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/src/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php index 887f4d396..51850e17f 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php +++ b/src/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php @@ -43,7 +43,7 @@ class WebProcessor implements ProcessorInterface * @param array|\ArrayAccess|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data * @param array|array|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data */ - public function __construct($serverData = null, ?array $extraFields = null) + public function __construct($serverData = null, array $extraFields = null) { if (null === $serverData) { $this->serverData = &$_SERVER; diff --git a/src/vendor/monolog/monolog/src/Monolog/Test/TestCase.php b/src/vendor/monolog/monolog/src/Monolog/Test/TestCase.php index bc0b425ea..c4e424967 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Test/TestCase.php +++ b/src/vendor/monolog/monolog/src/Monolog/Test/TestCase.php @@ -22,8 +22,6 @@ use Monolog\Formatter\FormatterInterface; * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger - * - * @internal feel free to reuse this to test your own handlers, this is marked internal to avoid issues with PHPStorm https://github.com/Seldaek/monolog/issues/1677 */ class TestCase extends \PHPUnit\Framework\TestCase { diff --git a/src/vendor/monolog/monolog/src/Monolog/Utils.php b/src/vendor/monolog/monolog/src/Monolog/Utils.php index d4ff4c040..726c98191 100644 --- a/src/vendor/monolog/monolog/src/Monolog/Utils.php +++ b/src/vendor/monolog/monolog/src/Monolog/Utils.php @@ -211,7 +211,7 @@ final class Utils $data = preg_replace_callback( '/[\x80-\xFF]+/', function ($m) { - return function_exists('mb_convert_encoding') ? mb_convert_encoding($m[0], 'UTF-8', 'ISO-8859-1') : utf8_encode($m[0]); + return utf8_encode($m[0]); }, $data ); @@ -249,7 +249,7 @@ final class Utils } $val = (int) $match['val']; - switch (strtolower($match['unit'])) { + switch (strtolower($match['unit'] ?? '')) { case 'g': $val *= 1024; case 'm': diff --git a/src/vendor/mpdf/mpdf/.github/CONTRIBUTING.md b/src/vendor/mpdf/mpdf/.github/CONTRIBUTING.md new file mode 100644 index 000000000..eef6959af --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/CONTRIBUTING.md @@ -0,0 +1,53 @@ +Contributing +============ + +Issue tracker +------------- + +The Issue tracker serves mainly as a place to report bugs and request new features. +Please do not abuse it as a general questions or troubleshooting location. + +General troubleshooting +------------- + +For these questions please use [Discussions](https://github.com/mpdf/mpdf/discussions). Add your enquiry +to appropriate category and as always, include a reproducible code example when applicable (see code example guidelines below). + +You can also use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) +at [Stack Overflow](https://stackoverflow.com/) +as the StackOverflow user base is more likely to answer you in a timely manner. +When doing so, make sure you comply to StackOverflow question guidelines. + +Bug reports +------------- + +* Bug reports **MUST** contain a small example in php/html that reproduces the bug. +* The code example **MUST** be reproducible by copy&paste assuming composer dependencies are installed. That means: + * No calling unrelated funcions, + * an actual final HTML code has to be present, pasting a template file is not enough, + * if the bug considers import or fonts, example source PDF/TTF/etc files have to be included. +* Failing to provide necessary information or not using the issue template will cause the issue to be closed until required information is provided. +* Please report one feature or one bug per issue. + +Feature requests +------------- + +Feature requests have to be labeled as such and have to include reasoning for the change in question. + + +Pull requests +------------- + +Pull requests should be always based on the default [development](https://github.com/mpdf/mpdf/tree/development) +branch except for backports to older versions. + +Guidelines: + +* Use an aptly named feature branch for the Pull request. +* Only files and lines affecting the scope of the Pull request must be affected. +* Make small, *atomic* commits that keep the smallest possible related code changes together. +* Code must be accompanied by a unit test testing expected behaviour whenever possible. +* To be incorporated, the PR should contain a change in the CHANGELOG.md file describing itself + +When updating a PR, do not create a new one, just `git push --force` to your former feature branch, the PR will +update itself. diff --git a/src/vendor/mpdf/mpdf/.github/FUNDING.yml b/src/vendor/mpdf/mpdf/.github/FUNDING.yml new file mode 100644 index 000000000..476013760 --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: https://www.paypal.me/mpdf diff --git a/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/01_bug_report.yml b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/01_bug_report.yml new file mode 100644 index 000000000..a88906a2e --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -0,0 +1,35 @@ +name: Bug report 🐛 +description: The library does not work as expected +body: + + - type: checkboxes + attributes: + label: Guidelines + description: Please confirm this is a bug report and not general troubleshooting. + options: + - label: I understand that [if I fail to adhere to contribution guidelines and/or fail to provide all required details, this issue may be closed without review](https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md). + required: true + + - type: textarea + attributes: + label: Description of the bug + validations: + required: true + + - type: input + attributes: + label: mPDF version + validations: + required: true + + - type: input + attributes: + label: PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions) + validations: + required: true + + - type: textarea + attributes: + label: Reproducible PHP+CSS+HTML snippet suffering by the error + validations: + required: true diff --git a/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/02_feature_request.yml b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/02_feature_request.yml new file mode 100644 index 000000000..88d9bdca6 --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/02_feature_request.yml @@ -0,0 +1,8 @@ +name: Feature request 🚀 +description: I would like to have a new functionality added +body: + - type: textarea + attributes: + label: Please describe the new functionality as best as you can. + validations: + required: true \ No newline at end of file diff --git a/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3c03ea0d0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: General questions and troubleshooting ❓ + url: https://github.com/mpdf/mpdf/discussions + about: You can use Github Discussions for general questions and troubleshooting. Please note that asking at Stack Overflow will probably be more successful. + - name: QA at Stack Overflow ❓ + url: https://stackoverflow.com/questions/tagged/mpdf + about: Ask at Stack Overflow for a greater chance of a quick and correct answer to your questions. Make sure to comply to SO rules, terms and conditions. diff --git a/src/vendor/mpdf/mpdf/.github/SECURITY.md b/src/vendor/mpdf/mpdf/.github/SECURITY.md new file mode 100644 index 000000000..71878d08a --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/SECURITY.md @@ -0,0 +1,5 @@ +How to disclose potential security issues +============ + +As mPDF does not have a domain or a dedicated contact apart from its Github repository, to prevent +disclosing maintainers' contacts publicly, please use [GitHub's Security Advisories system](https://github.com/mpdf/mpdf/security/advisories). \ No newline at end of file diff --git a/src/vendor/mpdf/mpdf/.github/workflows/coverage.yml b/src/vendor/mpdf/mpdf/.github/workflows/coverage.yml new file mode 100644 index 000000000..9ae56589d --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/workflows/coverage.yml @@ -0,0 +1,42 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Code coverage" + +on: + push: + branches: + - "development" + - "coverage" + +jobs: + + coverage: + + name: "Code coverage" + + runs-on: ${{ matrix.operating-system }} + + strategy: + matrix: + php-version: + - "7.4" + + operating-system: [ubuntu-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "xdebug" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring, gd, bcmath, bz2" + tools: composer:v2 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "Code coverage" + run: composer coverage diff --git a/src/vendor/mpdf/mpdf/.github/workflows/cs.yml b/src/vendor/mpdf/mpdf/.github/workflows/cs.yml new file mode 100644 index 000000000..c2a46d08e --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/workflows/cs.yml @@ -0,0 +1,43 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Coding standard check" + +on: + pull_request: + push: + branches: + - "development" + - "test" + +jobs: + + cs: + + name: "Coding standard" + + runs-on: ${{ matrix.operating-system }} + + strategy: + matrix: + php-version: + - "7.4" + + operating-system: [ubuntu-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring" + tools: composer:v2 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "CS" + run: composer cs diff --git a/src/vendor/mpdf/mpdf/.github/workflows/static-analysis.yml b/src/vendor/mpdf/mpdf/.github/workflows/static-analysis.yml new file mode 100644 index 000000000..3f97c7c94 --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/workflows/static-analysis.yml @@ -0,0 +1,44 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Static Analysis check" + +on: + pull_request: + push: + branches: + - "master" + - "development" + - "test" + +jobs: + + stan: + + name: "Static Analysis check" + + runs-on: ${{ matrix.operating-system }} + + strategy: + matrix: + php-version: + - "8.2" + + operating-system: [ubuntu-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring" + tools: composer:v2 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress && composer require \"phpstan/phpstan:^2.0\"" + + - name: "Static Analysis check" + run: vendor/bin/phpstan --no-progress diff --git a/src/vendor/mpdf/mpdf/.github/workflows/tests.yml b/src/vendor/mpdf/mpdf/.github/workflows/tests.yml new file mode 100644 index 000000000..9ec2f3283 --- /dev/null +++ b/src/vendor/mpdf/mpdf/.github/workflows/tests.yml @@ -0,0 +1,55 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Tests" + +on: + pull_request: + push: + branches: + - "master" + - "development" + - "test" + +jobs: + + tests: + + name: "Tests" + + runs-on: ${{ matrix.operating-system }} + + strategy: + fail-fast: false + matrix: + php-version: + - "5.6" + - "7.0" + - "7.1" + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + - "8.2" + - "8.3" + - "8.4" + operating-system: [ubuntu-latest, windows-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring, gd, bcmath, bz2" + tools: composer:v2 + ini-values: error_reporting=-1 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "Tests" + run: composer test diff --git a/src/vendor/mpdf/mpdf/CHANGELOG.md b/src/vendor/mpdf/mpdf/CHANGELOG.md new file mode 100644 index 000000000..a05d65086 --- /dev/null +++ b/src/vendor/mpdf/mpdf/CHANGELOG.md @@ -0,0 +1,801 @@ +mPDF 8.2.x +=========================== + +New features +------------ +* Watermark text can now be colored using \Mpdf\Watermark DTO. \Mpdf\WatermarkImage DTO for images. (#1876) +* Added support for `psr/http-message` v2 without dropping v1. (@markdorison, @apotek, @greg-1-anderson, @NigelCunningham #1907) +* PHP 8.3 support in mPDF 8.2.1 +* Add support for `page-break-before: avoid;` and `page-break-after: avoid;` for tr elements inside tables + +Bugfixes +-------- + +* Replace character entities with characters when processing the `code` attribute in the `` tag + +mPDF 8.1.x +=========================== + +New features +------------ + +* Service container for internal services +* Set /Lang entry for better accessibility when document language is available (@cuongmits, #1418) +* More verbose helper methods for `Output`: `OutputBinaryData`, `OutputHttpInline`, `OutputHttpDownload`, `OutputFile` (since v8.1.2) +* Set font-size to `auto` in textarea and input in active forms to resize the font-size (@ChrisB9, #1721) +* PHP 8.2 support in mPDF 8.1.3 +* Added support for `psr/log` v3 without dropping v2. (@markdorison, @apotek, @greg-1-anderson, #1857) + +Bugfixes +-------- + +* Better exception message about fonts with MarkGlyphSets (Fix for #1408) +* Updated Garuda font with fixed "k" character (Fix for #1440) +* Testing and suppressing PNG file conversion errors +* Prevent hyphenation of urls starting with https and e-mail addresses (@HKandulla, #1634) +* Colorspace restrictor reads mode from Mpdf and works again (Fix for #1094) +* Prevent exception when multiple columns wrap to next page +* Update default `curlUserAgent` configuration variable from Firefox 13 to 108 + +mPDF 8.0.x +=========================== + +* Ability to customize User-Agent header in the HTTP requests sent by cURL (@samuelecat, #1229) +* Add Page Number Myanmar Language Support (@MinKyawNyunt, #1201) +* new `Mpdf\Exception\FontException` extending base `MpdfException` was introduced and is thrown on Font manipulation +* A bit cleaner exception messages for font-related errors +* Use atomic cache writing. (@PATROMO, #1186) +* Fix: "Undefined index: group" when calling MultiCell when using font without OTL data (@Kekos, #1213, #941) +* Add C128RAW barcode type to create any barcode (ex: subtype change in middle of barcode) (#1124) +* Add proxy support to curl +* Fixed date and time format in the informations dictionary (#1083, @peterdevpl) +* Checking allowed stream wrappers in CssManager +* PHP 7.4 support (until final 7.4 release with composer --ignore-platform-reqs) +* Improve debugging of remote content issues (@ribeirobreno) +* Added `exposeVersion` configuration variable allowing to hide mPDF version from Producer tag and HTTP headers +* Added the check for JPEG SOF header 0xFF 0xC1 (extended) (@jamiejones85) +* Allows setting `none` as zoom mode in `SetDisplayMode` method, so that OpenAction is not written (#602) +* Allowed image stream whitelist to be customised (#1005, thanks @jakejackson) +* Fixed parsing of top-left-bottom-right CSS rules with !important (#1009) +* Fixed skipping ordered list numbering with page-break-inside: avoid (#339) +* Compound classes selector support, like `.one.two` or `div.message.special` (#538, @peterdevpl) +* Fixed CMYK colors in text-shadow (#1115, @lexilya) +* Skip non supported wrappers when resolving paths (#1204, @MarkVaughn) +* Fixed SVGs using a style tag, has styles ignored ( Requires ext-dom ) (#450, @antman3351) +* Allows `{nb}`, `{nbpg}`, `{PAGENO}` and `{DATE ...}` substitution in body (#172 and #267, @Dasc3er) +* Cache now creates a dedicated subdirectory `/mpdf`. +* It is possible to disable automatic cache cleanup with `cacheCleanupInterval` config variable +* PHP 8.0 is supported since 8.0.10 (#1263) +* Fix: First header of named page is added twice (@antman3351, #1320) +* Added `curlExecutionTimeout` configuration variable allowing to `CURLOPT_TIMEOUT` when fetching remote content +* Fix: Not all combinations were generated for more than three compound classes (@JeppeKnockaert) +* Added `quiet_zone_left` and `quiet_zone_right` to barcodes which support quiet zones in order to customize its width +* Updated `CssManager` to use the `RemoteContentFetcher` class instead of `curl` natively (@greew) +* Added optional `continue2pages` parameter to `SetDocTemplate` method, allowing a template to continue the last 2 pages alternately (@bmg-ruudv) +* Ensure that all digits of a string are hexadecimal before decoding in ColorConverter (@derklaro) +* Fix: Using mpdf in phar package leads to weird errors (#1504, @sandreas) +* WEBP images support (#1525) + + +mPDF 8.0.0 +=========================== + +### 15/03/2019 + +* Updated FPDI dependency to version 2 (thanks a lot, @JanSlabon) + - removed `SetImportUse` method + - case of `ImportPage` method changed to `importPage` + - similarly, case of `setSourceFile` and `useTemplate` was changed to a lowercase first letter. + - signature of `importPage` changed + - returned value of `useTemplate` changed +* Moved QRCode generating code portions to external package _mpdf/qrcode_ + - This reduced package size considerably (ca 6MB) +* Fraction sizes without leading zeros allowed for font sizes (#973, thanks @peterdevpl) +* WriteHTML is now strict about used `$mode` parameter (#915, thanks, @tomtomau) +* Fixed regression in nested tables (#860, thanks, @machour) +* Scientific notation handling in CSS font sizes (#753, thanks, @peterdevpl) + + +mPDF 7.1.x +=========================== + +* PHAR security issue fixed (thanks, @jakejackson) +* Font temporary data saved as JSON instead of generating PHP files (thanks, @jakejackson) +* cURL handling enhancements (thanks, @jakejackson) +* SVG parsing fixes (thanks, @achretien) +* Write PDF content with *Writer service classes +* PHP 7.3 is supported +* Added myclabs/deepcopy dependency, fixed TOC page numbering (thanks, @jakejackson) +* Custom color for QR codes +* Added support for orientation config key +* Code and tests cleanups and enhancements + - PHPUnit dedicated assertions (thanks, @carusogabriel) + - WriteHTML part constants (thanks, @tomtomau) + - Various notice fixes (kudos to all respective authors) + +mPDF 7.0.x +=========================== + +* Allow passing file content or file path to `SetAssociatedFiles` (#558) +* Allowed ^1.4 and ^2.0 of paragon/random_compat to allow wider usage +* Fix of undefined _getImage function (#539) +* Code cleanup +* Better writable rights for temp dir validation (#534) +* Fix displaying dollar character in footer with core fonts (#520) +* Fixed missed code2utf call (#531) +* Refactored and cleaned-up classes and subnamespaces + + +mPDF 7.0.0 +=========================== + +### 19/10/2017 + +Backward incompatible changes +----------------------------- + +- PHP `^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0` is required. +- Entire project moved under `Mpdf` namespace + - Practically all classes renamed to use `PascalCase` and named to be more verbose + - Changed directory structure to comply to `PSR-4` +- Removed explicit require calls, replaced with Composer autoloading +- Removed configuration files + - All configuration now done via `__construct` parameter (see below) +- Changed `\Mpdf\Mpdf` constructor signature + - Class now accepts only single array `$config` parameter + - Array keys are former `config.php` and `config_fonts.php` properties + - Additionally, former constructor parameters can be used as keys +- `tempDir` directory now must be writable, otherwise an exception is thrown +- ICC profile is loaded as entire path to file (to prevent a need to write inside vendor directory) +- Moved examples to separate repository +- Moved `TextVars` constants to separate class +- Moved border constants to separate class +- `scriptToLang` and `langToFont` in separate interfaced class methods +- Will now throw an exception when `mbstring.func_overload` is set +- Moved Glyph operator `GF_` constants in separate `\Mpdf\Fonts\GlyphOperator` class +- All methods in Barcode class renamed to camelCase including public `dec_to_hex` and `hex_to_dec` +- Decimal conversion methods (to roman, cjk, etc.) were moved to classes in `\Mpdf\Conversion` namespace +- Images in PHP variables (``) were moved from direct Mpdf properties to `Mpdf::$imageVars` public property array +- Removed global `_SVG_AUTOFONT` and `_SVG_CLASSES` constants in favor of `svgAutoFont` and `svgClasses` configuration keys +- Moved global `_testIntersect`, `_testIntersectCircle` and `calc_bezier_bbox` fucntions inside `Svg` class as private methods. + - Changed names to camelCase without underscores and to `computeBezierBoundingBox` +- Security: Embedded files via `` custom tag must be explicitly allowed via `allowAnnotationFiles` configuration key +- `fontDir` property of Mpdf class is private and must be accessed via configuration variable with array of paths or `AddFontDirectory` method +- QR code `` element now treats `\r\n` and `\n` as actual line breaks +- cURL is prefered over socket when downloading images. +- Removed globally defined functions from `functions.php` in favor of `\Mpdf\Utils` classes `PdfDate` and `UtfString`. + - Unused global functions were removed entirely. + + +Removed features +---------------- + +- Progressbar support +- JpGraph support +- `error_reporting` changes +- Timezone changes +- `compress.php` utility +- `_MPDF_PATH` and `_MPDF_URI` constants +- `_MPDF_TEMP_PATH` constant in favor of `tempDir` configuration variable +- `_MPDF_TTFONTDATAPATH` in favor of `tempDir` configuration variable +- `_MPDFK` constant in favor of `\Mpdf\Mpdf::SCALE` class constant +- `FONT_DESCRIPTOR` constant in favor of `fontDescriptor` configuration variable +- `_MPDF_SYSTEM_TTFONTS` constant in favor of `fontDir` configuration variable with array of paths or `AddFontDirectory` method +- HTML output of error messages and debugs +- Formerly deprecated methods + + +Fixes and code enhancements +---------------------------- + +- Fixed joining arab letters +- Fixed redeclared `unicode_hex` function +- Converted arrays to short syntax +- Refactored and tested color handling with potential conversion fixes in `hsl*()` color definitions +- Refactored `Barcode` class with separate class in `Mpdf\Barcode` namespace for each barcode type +- Fixed colsum calculation for different locales (by @flow-control in #491) +- Image type guessing from content separated to its own class + + +New features +------------ + +- Refactored caching (custom `Cache` and `FontCache` classes) +- Implemented `Psr\Log\LoggerAware` interface + - All debug and additional messages are now sent to the logger + - Messages can be filtered based on `\Mpdf\Log\Context` class constants +- `FontFileFinder` class allowing to specify multiple paths to search for fonts +- `MpdfException` now extends `ErrorException` to allow specifying place in code where error occured +- Generating font metrics moved to separate class +- Added `\Mpdf\Output\Destination` class with verbose output destination constants +- Availability to set custom default CSS file +- Availability to set custom hyphenation dictionary file +- Refactored code portions to new "separate" classes: + - `Mpdf\Color\*` classes + - `ColorConvertor` + - `ColorModeConvertor` + - `ColorSpaceRestrictor` + - `Mpdf\SizeConvertor` + - `Mpdf\Hyphenator` + - `Mpdf\Image\ImageProcessor` + - `Mpdf\Image\ImageTypeGuesser` + - `Mpdf\Conversion\*` classes +- Custom watermark angle with `watermarkAngle` configuration variable +- Custom document properties (idea by @zarubik in #142) +- PDF/A-3 associated files + additional xmp rdf (by @chab in #130) +- Additional font directories can be added via `addFontDir` method +- Introduced `cleanup` method which restores original `mb_` encoding settings (see #421) +- QR code `` element now treats `\r\n` and `\n` as actual line breaks +- Customizable following of 3xx HTTP redirects, validation of SSL certificates, cURL timeout. + - `curlFollowLocation` + - `curlAllowUnsafeSslRequests` + - `curlTimeout` +- QR codes can be generated without a border using `disableborder="1"` HTML attribute in `` tag + + +Git repository enhancements +--------------------------- + +- Added contributing guidelines +- Added Issue template + + +mPDF 6.1.0 +=========================== + +### 26/04/2016 + +- Composer updates + - First release officially supporting Composer + - Updated license in composer.json + - Chmod 777 on dirs `ttfontdata`, `tmp`, `graph_cache` after composer install +- Requiring PHP 5.4.0+ with Composer +- Code style + - Reformated (almost) all PHP files to keep basic code style + - Removed trailing whitespaces + - Converted all txt, php, css, and htm files to utf8 + - Removed closing PHP tags + - Change all else if calls to elseif +- Added base PHPUnit tests +- Added Travis CI integration with unit tests +- Changed all `mPDF::Error` and `die()` calls to throwing `MpdfException` +- PDF Import changes + - FPDI updated to 1.6.0 to fix incompatible licenses + - FPDI loaded from Composer or manually only +- Removed iccprofiles/CMYK directory +- Renamed example files: change spaces to underscores to make scripting easier +- Fixed `LEDGER` and `TABLOID` paper sizes +- Implemented static cache for mpdf function `ConvertColor`. +- Removed PHP4 style constructors +- Work with HTML tags separated to `Tag` class +- Fixed most Strict standards PHP errors +- Add config constant so we can define custom font data +- HTML + - fax & tel support in href attribute + - Check $html in `$mpdf->WriteHTML()` to see if it is an integer, float, string, boolean or + a class with `__toString()` and cast to a string, otherwise throw exception. +- PHP 7 + - Fix getting image from internal variable in PHP7 (4dcc2b4) + - Fix PHP7 Fatal error: `'break' not in the 'loop' or 'switch' context` (002bb8a) +- Fixed output file name for `D` and `I` output modes (issue #105, f297546) + +mPDF 6.0 +=========================== + +### 20/12/2014 + +New features / Improvements +--------------------------- +- Support for OpenTypeLayout tables / features for complex scripts and Advances Typography. +- Improved bidirectional text handling. +- Improved line-breaking, including for complex scripts e.g. Lao, Thai and Khmer. +- Updated page-breaking options. +- Automatic language mark-up and font selection using autoScriptToLang and autoLangToFont. +- Kashida for text-justification in arabic scripts. +- Index collation for non-ASCII characters. +- Index mark-up allowing control over layout using CSS. +- `{PAGENO}` and `{nbpg}` can use any of the number types as in list-style e.g. set in `` using pagenumstyle. +- CSS support for lists. +- Default stylesheet - `mpdf.css` - updated. + +Added CSS support +----------------- +- lang attribute selector e.g. :lang(fr), [lang="fr"] +- font-variant-position +- font-variant-caps +- font-variant-ligatures +- font-variant-numeric +- font-variant-alternates - Only [normal | historical-forms] supported (i.e. most are NOT supported) +- font-variant - as above, and except for: east-asian-variant-values, east-asian-width-values, ruby +- font-language-override +- font-feature-settings +- text-outline is now supported on TD/TH tags +- hebrew, khmer, cambodian, lao, and cjk-decimal recognised as values for "list-style-type" in numbered lists and page numbering. +- list-style-image and list-style-position +- transform (on `` only) +- text-decoration:overline +- image-rendering +- unicode-bidi (also `` tag) +- vertical-align can use lengths e.g. 0.5em +- line-stacking-strategy +- line-stacking-shift + +mPDF 5.7.4 +================ + +### 15/12/2014 + +Bug Fixes & Minor Additions +--------------------------- +- SVG images now support embedded images e.g. `` +- SVG images now supports `` element e.g. ``, and also `` +- SVG images now can use Autofont (see top of `classes/svg.php` file) +- SVG images now has limited support for CSS classes (see top of `classes/svg.php` file) +- SVG images - style inheritance improved +- SVG images - improved handling of comments and other extraneous code +- SVG images - fix to ensure opacity is reset before another element +- SVG images - font-size not resetting after a `` element +- SVG radial gradients bug (if the focus [fx,fy] lies outside circle defined by [cx,cy] and r) cf. pservers-grad-15-b.svg +- SVG allows spaces in attribute definitions in `` or `` e.g. `` +- SVG text which contains a `<` sign, it will break the text - now processed as `<` (despite the fact that this does not conform to XML spec) +- SVG images - support automatic font selection and (minimal) use of CSS classes - cf. the defined constants at top of svg.php file +- SVG images - text-anchor now supported as a CSS style, as well as an HTML attribute +- CSS support for :nth-child() selector improved to fully support the draft CSS3 spec - http://www.w3.org/TR/selectors/#nth-child-pseudo + [NB only works on table columns or rows] +- text-indent when set as "em" - incorrectly calculated if last text in line in different font size than for block +- CSS not applying cascaded styles on `` elements - [changed MergeCSS() type to INLINE for 'A', LEGEND, METER and PROGRESS] +- fix for underline/strikethrough/overline so that line position(s) are based correctly on font-size/font in nested situations +- Error: Strict warning: Only variables should be passed by reference - in PHP5.5.9 +- bug accessing images from some servers (HTTP 403 Forbidden whn accessed using fopen etc.) +- Setting page format incorrectly set default twice and missed some options +- bug fixed in Overwrite() when specifying replacement as a string +- barcode C93 - updated C93 code from TCPDF because of bug - incorrect checksum character for "153-2-4" +- Tables - bug when using colspan across columns which may have a cell width specified + cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug +- Tables - cell height (when specified) is not resized when table is shrunk +- Tables - if table width specified, but narrower than minimum cell wdith, and less than page width - table will expand to + minimum cell width(s) as long as $keep_table_proportions = true +- Tables - if using packTableData, and borders-collapse, wider border is overwriting content of adjacent cell + Test case: + ``` + + + +
Hallo world
Hallo world
+ ``` +- Images - image height is reset proportional to original if width is set to maximum e.g. `` +- URL handling changed to work with special characters in path fragments; affects `
` links, `` images and + CSS url() e.g background-image + - also to ignore `../` included as a query value +- Barcodes with bottom numerals e.g. EAN-13 - incorrect numeral size when using core fonts + +-------------------------------- + +NB Spec. for embedded SVG images: +as per http://www.w3.org/TR/2003/REC-SVG11-20030114/struct.html#ImageElement +Attributes supported: +- x +- y +- xlink:href (required) - can be jpeg, png or gif image - not vector (SVG or WMF) image +- width (required) +- height (required) +- preserveAspectRatio + +Note: all attribute names and values are case-sensitive +width and height cannot be assigned by CSS - must be attributes + +mPDF 5.7.3 +================ + +### 24/8/2014 + +Bug Fixes & Minor Additions +--------------------------- + +- Tables - cellSpacing and cellPadding taking preference over CSS stylesheet +- Tables - background images in table inside HTML Footer incorrectly positioned +- Tables - cell in a nested table with a specified width, should determine width of parent table cell + (cf. http://www.mpdf1.com/forum/discussion/1648/nested-table-bug-) +- Tables - colspan (on a row after first row) exceeds number of columns in table +- Gradients in Imported documents (mPDFI) causing error in some browsers +- Fatal error after page-break-after:always on root level block element +- Support for 'https/SSL' if file_get_contents_by_socket required (e.g. getting images with allow_url_fopen turned off) +- Improved support for specified ports when getting external CSS stylesheets e.g. www.domain.com:80 +- error accessing local .css files with dummy queries (cache-busting) e.g. mpdfstyleA4.css?v=2.0.18.9 +- start of end tag in PRE incorrectly changed to < +- error thrown when open.basedir restriction in effect (deleting temporary files) +- image which forces pagebreak incorrectly positioned at top of page +- [changes to avoid warning notices by checking if (isset(x)) before referencing it] +- text with letter-spacing set inside table which needs to be resixed (shrunk) - letter-spacing was not adjusted +- nested table incorrectly calculating width and unnecessarily wrapping text +- vertical-align:super|sub can be nested using `` elements +- inline elements can be nested e.g. text `text13text` text +- CSS vertical-align:0.5em (or %) now supported +- underline and strikethrough now use the parent inline block baseline/fontsize/color for child inline elements *** change in behaviour + (Adjusts line height to take account of superscript and subscript except in tables) +- nested table incorrectly calculating width and unnecessarily wrapping text +- tables - font size carrying over from one nested table to the next nested table +- tables - border set as attribute on `` overrides border set as CSS on `` not printing at all (since v5.7) +- list-style incorrectly overriding list-style-type in cascading CSS +- page-break-after:avoid not taking into account bottom padding and margin when estimating if next line can fit on page +- images not displayed when using "https://" if images are referenced by src="//domain.com/image" +- +aCJK incorrectly parsed when instantiating class e.g. new mpDF('ja+aCJK') +- line-breaking - zero-width object at end of line (e.g. index entry) causing a space left untrimmed at end of line +- ToC since v5.7 incorrectly handling non-ascii characters, entities or tags +- cell height miscalculated when using hard-hyphenate +- border colors set with transparency not working +- transparency settings for stroke and fill interfering with one another +- 'float' inside a HTML header/footer - not clearing the float before first line of text +- error if script run across date change at midnight +- temporary file name collisions (e.g. when processing images) if numerous users +- `` position attribute not working +- `<` (less-than sign) inside a PRE element, and NOT start of a valid tag, was incorrectly removed +- file attachments not opening in Reader XI +- JPG images not recognised if not containing JFIF or Exif markers +- instance of preg_replace with /e modifier causing error in PHP 5.5 +- correctly handle CSS URLs with no scheme +- Index entries causing errors when repeat entries are used within page-break-inside:avoid, rotated tables etc. +- table with fixed width column and long word in cell set to colspan across this column (adding spare width to all columns) +- incorrect hyphenation if multiple soft-hyphens on line before break +- SVG images - objects contained in `` being displayed +- SVG images - multiple, or quoted fonts e.g. style="font-family:'lucida grande', verdana" not recognised +- SVG images - line with opacity=0 still visible (only in some PDF viewers/browsers) +- text in an SVG image displaying with incorrect font in some PDF viewers/browsers +- SVG images - fill:RGB(0,0,0) not recognised when uppercase +- background images using data:image\/(jpeg|gif|png);base64 format - error when reading in stylesheet + +New CSS support +--------------- + +- added support for style="opacity:0.6;" in SVG images - previously only supported style="fill-opacity:0.6; stroke-opacity: 0.6;" +- improved PNG image handling for some cases of alpha channel transparency +- khmer, cambodian and lao recognised as list-style-type for numbered lists + +SVG Images +---------- + +- Limited support for `` and `` + +mPDF 5.7.1 +================ +## 01/09/2013 + +1) FILES: mpdf.php + +Bug fix; Dollar sign enclosed by `
` tag causing error.
+Test e.g.: `
Test $1.00 Test
Test $2.00 Test
Test $3.00 Test
Test $4.00 Test
` + +----------------------------- + +2) FILES: includes/functions.php AND mpdf.php + +Changes to `preg_replace` with `/e` modifier to use `preg_replace_callback` +(/e depracated from PHP 5.5) + +----------------------------- + +3) FILES: classes/barcode.php + +Small change to function `barcode_c128()` which allows ASCII 0 - 31 to be used in C128A e.g. chr(13) in: +`` + +----------------------------- + +4) FILES: mpdf.php + +Using $use_kwt ("keep-[heading]-with-table") if `

` before table is on 2 lines and pagebreak occurs after first line +the first line is displayed at the bottom of the 2nd page. +Edited so that $use_kwt only works if the HEADING is only one line. Else ignores (but prints correctly) + +----------------------------- + +5) FILES: mpdf.php + +Clearing old temporary files from `_MPDF_TEMP_PATH` will now ignore "hidden" files e.g. starting with a "`.`" `.htaccess`, `.gitignore` etc. +and also leave `dummy.txt` alone + + +mPDF 5.7 +=========================== + +### 14/07/2013 + +Files changed +------------- +- config.php +- mpdf.php +- classes/tocontents.php +- classes/cssmgr.php +- classes/svg.php +- includes/functions.php +- includes/out.php +- examples/formsubmit.php [Important - Security update] + +Updated Example Files in /examples/ +----------------------------------- + +- All example files +- mpdfstyleA4.css + +config.php +---------- + +Removed: +- $this->hyphenateTables +- $this->hyphenate +- $this->orphansAllowed +Edited: +- "hyphens: manual" - Added to $this->defaultCSS +- $this->allowedCSStags now includes '|TEXTCIRCLE|DOTTAB' +New: +- $this->decimal_align = array('DP'=>'.', 'DC'=>',', 'DM'=>"\xc2\xb7", 'DA'=>"\xd9\xab", 'DD'=>'-'); +- $this->h2toc = array('H1'=>0, 'H2'=>1, 'H3'=>2); +- $this->h2bookmarks = array('H1'=>0, 'H2'=>1, 'H3'=>2); +- $this->CJKforceend = false; // Forces overflowng punctuation to hang outside right margin (used with CJK script) + + +Backwards compatability +----------------------- + +Changes in mPDF 5.7 may cause some changes to the way your documents appear. There are two main differences: +1) Hyphenation. To retain appearance compatible with earlier versions, set the CSS property "hyphens: auto" whenever + you previously used $mpdf->hyphenate=true; +2) Table of Contents - appearance can now be controlled with CSS styles. By default, in mPDF 5.7, no styling is applied so you will get: + - No indent (previous default of 5mm) - ($tocindent is ignored) + - Any font, font-size set ($tocfont or $tocfontsize) will not work + - HyperLinks will appear with your default appearance - usually blue and underlined + - line spacing will be narrower (can use line-height or margin-top in CSS) + +New features / Improvements +--------------------------- +- Layout of Table of Content ToC now controlled using CSS styles +- Text alignment on decimal mark inside tables +- Automatically generated bookmarks and/or ToC entries from H1 - H6 tags +- Support for unit of "rem" as size e.g. font-size: 1rem; +- Origin and clipping for background images and gradients controlled by CSS i.e. background-origin, background-size, background-clip +- Text-outline controlled by CSS (compatible with CSS3 spec.) +- Use of `` enhanced by custom CSS "outdent" property +- Image HTML attributes `` added: max-height, max-width, min-height and min-width +- Spotcolor can now be defined as it is used e.g. color: spot(PANTONE 534 EC, 100%, 85, 65, 47, 9); +- Lists - added support for "start" attribute in `
    ` e.g. `
      ` +- Hyphenation controlled using CSS, consistent with CSS3 spec. +- Line breaking improved to avoid breaks within words where HTML tags are used e.g. H20 +- Line breaking in CJK scripts improved (and ability to force hanging punctuation) +- Numerals in a CJK script are kept together +- RTL improved support for phrases containing numerals and \ and / +- Bidi override codes supported - Right-to-Left Embedding [RLE] U+202B, Left-to-Right Embedding [LRE] U+202A, + U+202C POP DIRECTIONAL FORMATTING (PDF) +- Support for `` in HTML - uses it to SetBasePath for relative URLs. +- HTML tag - added support for `` or `` - converted to a soft-hyphen +- CSS now takes precedence over HTML attribute e.g. `
` +- tables - if table width set to 100% and one cell/column is empty with no padding/border, sizing incorrectly + (http://www.mpdf1.com/forum/discussion/1886/td-fontsize-in-nested-table-bug-#Item_5) +- `
` added as recognised tag +- CSS style transform supported on `` element (only) + All transform functions are supported except matrix() i.e. translate(), translateX(), translateY(), skew(), skewX(), skewY(), + scale(), scaleX(), scaleY(), rotate() + NB When using Columns or Keep-with-table (use_kwt), cannot use transform +- CSS background-color now supported on `` element +- @page :first not recognised unless @page {} has styles set +- left/right margins not allowed on @page :first + +mPDF 5.7.2 +================ + +### 28/12/2013 + +Bug Fixes +--------- + +- `
` + +Added CSS support +----------------- +- max-height, max-width, min-height and min-width for images `` +- "hyphens: none|manual|auto" as per CSS3 spec. +- Decimal mark alignment e.g. text-align: "." center; +- "rem" accepted as a valid (font)size in CSS e.g. font-size: 1.5rem +- text-outline, text-outline-width and text-outline-color supported everywhere except in tables (blur not supported) +- background-origin, background-size, background-clip are now supported everywhere except in tables +- "visibility: hidden|visible|printonly|screenonly" for inline elements e.g. `` +- Colors: device-cmyk(c,m,y,k) as per CSS3 spec. For consistency, device-cmyka also supported (not CSS3 spec) +- "z-index" can be used to utilise layers in the PDF document +- Custom CSS property added: "outdent" - opposite of indent + +The HTML elements `` and `` can now have CSS properties applied to them. + +Bug fixes +--------- +- SVG images - path including e.g. 1.234E-15 incorrectly parsed (not recognising capital E) +- Tables - if a table starts when the Y position on page is below bottom margin caused endless loop +- Float-ing DIVs - starting a float at bottom of page and it causes page break before anything output, second new page is forced +- Tables - Warning notice now given in Table footer or header if `` placed after `` and table spans page +- Columns - block with border-width wider than the length of the border line, line overflows +- Columns - block with no padding containing a block with borders but no backgound colour, borders not printed +- Table in Columns - when background color set by surrounding block element - colour missing for height of half bottom border. +- TOCpagebreakByArray() when called by function was not adding the pagebreak +- Border around block element - dashed not showing correctly (not resetting linewidth between different edges) +- Double border in table - when background colour set in surrounding block element - shows as black line between the 2 bits of double +- Borders around DIVs - "double" border problem if not all 4 sides equally - fixed +- Borders around DIVs - solid (and double) borders overlap as in tables - now fixed so mitred joins as in browser + [Inadvertently improves borders in Columns because of change in LineCap] +- Page numbering - $mpdf->pagenumSuffix etc not suppressed in HTML headers/footers if number suppressed +- Page numbering - Page number total {nbpg} incorrect - e.g. showing decreasing numbers through document, when ToC present +- RTL numerals - incorrectly reversing a number followed by a comma +- Transform to uppercase/lowercase not working for chars > ASCII 128 when using core fonts +- TOCpagebreak - Not setting TOC-FOOTER +- TOCpagebreak - toc-even-header-name etc. not working +- Parsing some relative URLs incorrectly +- Textcircle - when moved to next page by "page-break-inside: avoid" +- Bookmarks will now work if jump more than one level e.g. 0,2,1 Inserts a new blank entry at level 1 +- Paths to img or stylesheets - incorrectly reading "//www.domain.com" i.e. when starting with two / +- data:image as background url() - incorrectly adjusting path on server if MPDF_PATH not specified (included in release mPDF 5.6.1) +- Image problem if spaces or commas in path using http:// URL (included in release mPDF 5.6.1) +- Image URL parsing rewritten to handle both urlencoded URLs and not urlencoded (included in release mPDF 5.6.1) +- `` fixed to allow color, font-size and font-family to be correctly used, avoid dots being moved to new page, and to work in RTL +- Table {colsum} summed figures in table header +- list-style-type (custom) colour not working +- `` toc-preHTML and toc-postHTML can now contain quotes + +mPDF 5.6 +=========================== + +### 20/01/2013 + +Files changed +------------- +- mpdf.php +- config.php +- includes/functions.php +- classes/meter.php +- classes/directw.php + + +config.php changes +------------------ + +- $this->allowedCSStags - added HTML5 tags + textcircle AND +- $this->outerblocktags - added HTML5 tags +- $this->defaultCSS - added default CSS properties + +New features / Improvements +--------------------------- +CSS support added for for min-height, min-width, max-height and max-width in `` + +Images embedded in CSS +- `` improved to make it more robust, and background: `url(data:image...` now added to work + +HTML5 tags supported +- as generic block elements: `
must precede in a table"); + } else { + return; + } + } + + + // Advance down page by half width of top border + if ($horf == 'H') { // Only if header + if ($table['borders_separate']) { + $adv = $table['border_spacing_V'] / 2 + $table['border_details']['T']['w'] + $table['padding']['T']; + } else { + $adv = $table['max_cell_border_width']['T'] / 2; + } + if ($adv) { + if ($this->table_rotate) { + $this->y += ($adv); + } else { + $this->DivLn($adv, $this->blklvl, true); + } + } + } + + $topy = $content[$firstrow][0]['y'] - $this->y; + + for ($i = $firstrow; $i <= $lastrow; $i++) { + $y = $this->y; + + /* -- COLUMNS -- */ + // If outside columns, this is done in PaintDivBB + if ($this->ColActive) { + // OUTER FILL BGCOLOR of DIVS + if ($this->blklvl > 0) { + $firstblockfill = $this->GetFirstBlockFill(); + if ($firstblockfill && $this->blklvl >= $firstblockfill) { + $divh = $content[$i][0]['h']; + $bak_x = $this->x; + $this->DivLn($divh, -3, false); + // Reset current block fill + $bcor = $this->blk[$this->blklvl]['bgcolorarray']; + $this->SetFColor($bcor); + $this->x = $bak_x; + } + } + } + /* -- END COLUMNS -- */ + + $colctr = 0; + foreach ($content[$i] as $tablehf) { + $colctr++; + $y = Arrays::get($tablehf, 'y', null) - $topy; + $this->y = $y; + // Set some cell values + $x = Arrays::get($tablehf, 'x', null); + if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page) % 2 == 0)) { // EVEN + $x = $x + $this->MarginCorrection; + } elseif (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page) % 2 == 1)) { // ODD + $x = $x + $this->MarginCorrection; + } + /* -- COLUMNS -- */ + // Added to correct for Columns + if ($this->ColActive) { + if ($this->directionality == 'rtl') { // *OTL* + $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* + } // *OTL* + else { // *OTL* + $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap); + } // *OTL* + } + /* -- END COLUMNS -- */ + + if ($colctr == 1) { + $x0 = $x; + } + + // mPDF ITERATION + if ($this->iterationCounter) { + foreach ($tablehf['textbuffer'] as $k => $t) { + if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) { + $vname = '__' . $m[1] . '_'; + if (!isset($this->$vname)) { + $this->$vname = 1; + } else { + $this->$vname++; + } + $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $tablehf['textbuffer'][$k][0]); + } + } + } + + $w = Arrays::get($tablehf, 'w', null); + $h = Arrays::get($tablehf, 'h', null); + $va = Arrays::get($tablehf, 'va', null); + $R = Arrays::get($tablehf, 'R', null); + $direction = Arrays::get($tablehf, 'direction', null); + $mih = Arrays::get($tablehf, 'mih', null); + $border = Arrays::get($tablehf, 'border', null); + $border_details = Arrays::get($tablehf, 'border_details', null); + $padding = Arrays::get($tablehf, 'padding', null); + $this->tabletheadjustfinished = true; + + $textbuffer = Arrays::get($tablehf, 'textbuffer', null); + + // Align + $align = Arrays::get($tablehf, 'a', null); + $this->cellTextAlign = $align; + + $this->cellLineHeight = Arrays::get($tablehf, 'cellLineHeight', null); + $this->cellLineStackingStrategy = Arrays::get($tablehf, 'cellLineStackingStrategy', null); + $this->cellLineStackingShift = Arrays::get($tablehf, 'cellLineStackingShift', null); + + $this->x = $x; + + if ($this->ColActive) { + if ($table['borders_separate']) { + $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0; + if ($tablefill) { + $color = $this->colorConverter->convert($tablefill, $this->PDFAXwarnings); + if ($color) { + $xadj = ($table['border_spacing_H'] / 2); + $yadj = ($table['border_spacing_V'] / 2); + $wadj = $table['border_spacing_H']; + $hadj = $table['border_spacing_V']; + if ($i == $firstrow && $horf == 'H') { // Top + $yadj += $table['padding']['T'] + $table['border_details']['T']['w']; + $hadj += $table['padding']['T'] + $table['border_details']['T']['w']; + } + if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1)) || (!isset($tablehf['rowspan']) && ($i + 1) == ($lastrow + 1))) && $horf == 'F') { // Bottom + $hadj += $table['padding']['B'] + $table['border_details']['B']['w']; + } + if ($colctr == 1) { // Left + $xadj += $table['padding']['L'] + $table['border_details']['L']['w']; + $wadj += $table['padding']['L'] + $table['border_details']['L']['w']; + } + if ($colctr == count($content[$i])) { // Right + $wadj += $table['padding']['R'] + $table['border_details']['R']['w']; + } + $this->SetFColor($color); + $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F'); + } + } + } + } + + if ($table['empty_cells'] != 'hide' || !empty($textbuffer) || !$table['borders_separate']) { + $paintcell = true; + } else { + $paintcell = false; + } + + // Vertical align + if ($R && intval($R) > 0 && isset($va) && $va != 'B') { + $va = 'B'; + } + + if (!isset($va) || empty($va) || $va == 'M') { + $this->y += ($h - $mih) / 2; + } elseif (isset($va) && $va == 'B') { + $this->y += $h - $mih; + } + + + // TABLE ROW OR CELL FILL BGCOLOR + $fill = 0; + if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor'] != 'transparent') { + $fill = $tablehf['bgcolor']; + $leveladj = 6; + } elseif (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor'] != 'transparent') { // Row color + $fill = $content[$i][0]['trbgcolor']; + $leveladj = 3; + } + if ($fill && $paintcell) { + $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings); + if ($color) { + if ($table['borders_separate']) { + if ($this->ColActive) { + $this->SetFColor($color); + $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F'); + } else { + $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color]; + } + } else { + if ($this->ColActive) { + $this->SetFColor($color); + $this->Rect($x, $y, $w, $h, 'F'); + } else { + $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color]; + } + } + } + } + + + /* -- BACKGROUNDS -- */ + if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell) { + $g = $this->gradient->parseBackgroundGradient($tablehf['gradient']); + if ($g) { + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']); + } else { + $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } + + if (isset($tablehf['background-image']) && $paintcell) { + if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'])) { + $g = $this->gradient->parseMozGradient($tablehf['background-image']['gradient']); + if ($g) { + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']); + } else { + $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } elseif ($tablehf['background-image']['image_id']) { // Background pattern + $n = count($this->patterns) + 1; + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($tablehf['background-image']['orig_w'], $tablehf['background-image']['orig_h'], $pw, $ph, $tablehf['background-image']['resize'], $tablehf['background-image']['x_repeat'], $tablehf['background-image']['y_repeat']); + $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'itype' => $tablehf['background-image']['itype']]; + if ($tablehf['background-image']['opacity'] > 0 && $tablehf['background-image']['opacity'] < 1) { + $opac = $this->SetAlpha($tablehf['background-image']['opacity'], 'Normal', true); + } else { + $opac = ''; + } + $this->writer->write(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE)); + } else { + $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $tablehf['background-image']['orig_w'], 'orig_h' => $tablehf['background-image']['orig_h'], 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $tablehf['background-image']['x_repeat'], 'y_repeat' => $tablehf['background-image']['y_repeat'], 'clippath' => '', 'resize' => $tablehf['background-image']['resize'], 'opacity' => $tablehf['background-image']['opacity'], 'itype' => $tablehf['background-image']['itype']]; + } + } + } + /* -- END BACKGROUNDS -- */ + + // Cell Border + if ($table['borders_separate'] && $paintcell && $border) { + $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($border_details['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($border_details['T']['w'] / 2), $w - $table['border_spacing_H'] - ($border_details['L']['w'] / 2) - ($border_details['R']['w'] / 2), $h - $table['border_spacing_V'] - ($border_details['T']['w'] / 2) - ($border_details['B']['w'] / 2), $border, $border_details, false, $table['borders_separate']); + } elseif ($paintcell && $border) { + $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer + } + + // Print cell content + if (!empty($textbuffer)) { + if ($horf == 'F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) { + $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$colctr - 1]); + $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $textbuffer[0][0]); + } + + if ($R) { + $cellPtSize = $textbuffer[0][11] / $this->shrin_k; + if (!$cellPtSize) { + $cellPtSize = $this->default_font_size; + } + $cellFontHeight = ($cellPtSize / Mpdf::SCALE); + $opx = $this->x; + $opy = $this->y; + $angle = intval($R); + + // Only allow 45 - 90 degrees (when bottom-aligned) or -90 + if ($angle > 90) { + $angle = 90; + } elseif ($angle > 0 && (isset($va) && $va != 'B')) { + $angle = 90; + } elseif ($angle > 0 && $angle < 45) { + $angle = 45; + } elseif ($angle < 0) { + $angle = -90; + } + + $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight); + if (isset($align) && $align == 'R') { + $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($padding['R'] + $border_details['R']['w']); + } elseif (!isset($align) || $align == 'C') { + $this->x += ($w / 2) + ($offset); + } else { + $this->x += ($offset) + ($cellFontHeight / 3) + ($padding['L'] + $border_details['L']['w']); + } + $str = ''; + foreach ($tablehf['textbuffer'] as $t) { + $str .= $t[0] . ' '; + } + $str = rtrim($str); + + if (!isset($va) || $va == 'M') { + $this->y -= ($h - $mih) / 2; // Undo what was added earlier VERTICAL ALIGN + if ($angle > 0) { + $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']) + ($mih - ($padding['T'] + $border_details['T']['w'] + $border_details['B']['w'] + $padding['B'])); + } elseif ($angle < 0) { + $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']); + } + } elseif (isset($va) && $va == 'B') { + $this->y -= $h - $mih; // Undo what was added earlier VERTICAL ALIGN + if ($angle > 0) { + $this->y += $h - ($border_details['B']['w'] + $padding['B']); + } elseif ($angle < 0) { + $this->y += $h - $mih + ($padding['T'] + $border_details['T']['w']); + } + } elseif (isset($va) && $va == 'T') { + if ($angle > 0) { + $this->y += $mih - ($border_details['B']['w'] + $padding['B']); + } elseif ($angle < 0) { + $this->y += ($padding['T'] + $border_details['T']['w']); + } + } + + $this->Rotate($angle, $this->x, $this->y); + $s_fs = $this->FontSizePt; + $s_f = $this->FontFamily; + $s_st = $this->FontStyle; + if (!empty($textbuffer[0][3])) { // Font Color + $cor = $textbuffer[0][3]; + $this->SetTColor($cor); + } + $this->SetFont($textbuffer[0][4], $textbuffer[0][2], $cellPtSize, true, true); + + $this->magic_reverse_dir($str, $this->directionality, $textbuffer[0][18]); + $this->Text($this->x, $this->y, $str, $textbuffer[0][18], $textbuffer[0][8]); // textvar + $this->Rotate(0); + $this->SetFont($s_f, $s_st, $s_fs, true, true); + $this->SetTColor(0); + $this->x = $opx; + $this->y = $opy; + } else { + if ($table['borders_separate']) { // NB twice border width + $xadj = $border_details['L']['w'] + $padding['L'] + ($table['border_spacing_H'] / 2); + $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] + $padding['R'] + $table['border_spacing_H']; + $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H'] / 2); + } else { + $xadj = $border_details['L']['w'] / 2 + $padding['L']; + $wadj = ($border_details['L']['w'] + $border_details['R']['w']) / 2 + $padding['L'] + $padding['R']; + $yadj = $border_details['T']['w'] / 2 + $padding['T']; + } + + $this->divwidth = $w - ($wadj); + $this->x += $xadj; + $this->y += $yadj; + $this->printbuffer($textbuffer, '', true, false, $direction); + } + } + $textbuffer = []; + + /* -- BACKGROUNDS -- */ + if (!$this->ColActive) { + if (isset($content[$i][0]['trgradients']) && ($colctr == 1 || $table['borders_separate'])) { + $g = $this->gradient->parseBackgroundGradient($content[$i][0]['trgradients']); + if ($g) { + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s]; + } else { + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } + + if (isset($content[$i][0]['trbackground-images']) && ($colctr == 1 || $table['borders_separate'])) { + if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'])) { + $g = $this->gradient->parseMozGradient($content[$i][0]['trbackground-images']['gradient']); + if ($g) { + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s]; + } else { + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } else { + $image_id = $content[$i][0]['trbackground-images']['image_id']; + $orig_w = $content[$i][0]['trbackground-images']['orig_w']; + $orig_h = $content[$i][0]['trbackground-images']['orig_h']; + $x_pos = $content[$i][0]['trbackground-images']['x_pos']; + $y_pos = $content[$i][0]['trbackground-images']['y_pos']; + $x_repeat = $content[$i][0]['trbackground-images']['x_repeat']; + $y_repeat = $content[$i][0]['trbackground-images']['y_repeat']; + $resize = $content[$i][0]['trbackground-images']['resize']; + $opacity = $content[$i][0]['trbackground-images']['opacity']; + $itype = $content[$i][0]['trbackground-images']['itype']; + + $clippath = ''; + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } else { + $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } + } + } + } + /* -- END BACKGROUNDS -- */ + + // TABLE BORDER - if separate OR collapsed and only table border + if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) { + $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2); + $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2); + $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2); + $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2); + $tbx = $x; + $tby = $y; + $tbw = $w; + $tbh = $h; + $tab_bord = 0; + $corner = ''; + if ($i == $firstrow && $horf == 'H') { // Top + $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2); + $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2); + $this->setBorder($tab_bord, Border::TOP); + $corner .= 'T'; + } + if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1))) && $horf == 'F') { // Bottom + $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2); + $this->setBorder($tab_bord, Border::BOTTOM); + $corner .= 'B'; + } + if ($colctr == 1 && $firstSpread) { // Left + $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2); + $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2); + $this->setBorder($tab_bord, Border::LEFT); + $corner .= 'L'; + } + if ($colctr == count($content[$i]) && $finalSpread) { // Right + $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2); + $this->setBorder($tab_bord, Border::RIGHT); + $corner .= 'R'; + } + $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']); + } + }// end column $content + $this->y = $y + $h; // Update y coordinate + }// end row $i + unset($table); + $this->colsums = []; + } + } + + /* -- END TABLES -- */ + + function SetHTMLHeader($header = '', $OE = '', $write = false) + { + + $height = 0; + if (is_array($header) && isset($header['html']) && $header['html']) { + $Hhtml = $header['html']; + if ($this->setAutoTopMargin) { + if (isset($header['h'])) { + $height = $header['h']; + } else { + $height = $this->_getHtmlHeight($Hhtml); + } + } + } elseif (!is_array($header) && $header) { + $Hhtml = $header; + if ($this->setAutoTopMargin) { + $height = $this->_getHtmlHeight($Hhtml); + } + } else { + $Hhtml = ''; + } + + if ($OE !== 'E') { + $OE = 'O'; + } + + if ($OE === 'E') { + if ($Hhtml) { + $this->HTMLHeaderE = []; + $this->HTMLHeaderE['html'] = $Hhtml; + $this->HTMLHeaderE['h'] = $height; + } else { + $this->HTMLHeaderE = ''; + } + } else { + if ($Hhtml) { + $this->HTMLHeader = []; + $this->HTMLHeader['html'] = $Hhtml; + $this->HTMLHeader['h'] = $height; + } else { + $this->HTMLHeader = ''; + } + } + + if (!$this->mirrorMargins && $OE == 'E') { + return; + } + if ($Hhtml == '') { + return; + } + + if ($this->setAutoTopMargin == 'pad') { + $this->tMargin = $this->margin_header + $height + $this->orig_tMargin; + if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { + $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; + } + } elseif ($this->setAutoTopMargin == 'stretch') { + $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding); + if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) { + $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin; + } + } + if ($write && $this->state != 0 && (($this->mirrorMargins && $OE == 'E' && ($this->page) % 2 == 0) || ($this->mirrorMargins && $OE != 'E' && ($this->page) % 2 == 1) || !$this->mirrorMargins)) { + $this->writeHTMLHeaders(); + } + } + + function SetHTMLFooter($footer = '', $OE = '') + { + $height = 0; + if (is_array($footer) && isset($footer['html']) && $footer['html']) { + $Fhtml = $footer['html']; + if ($this->setAutoBottomMargin) { + if (isset($footer['h'])) { + $height = $footer['h']; + } else { + $height = $this->_getHtmlHeight($Fhtml); + } + } + } elseif (!is_array($footer) && $footer) { + $Fhtml = $footer; + if ($this->setAutoBottomMargin) { + $height = $this->_getHtmlHeight($Fhtml); + } + } else { + $Fhtml = ''; + } + + if ($OE !== 'E') { + $OE = 'O'; + } + + if ($OE === 'E') { + if ($Fhtml) { + $this->HTMLFooterE = []; + $this->HTMLFooterE['html'] = $Fhtml; + $this->HTMLFooterE['h'] = $height; + } else { + $this->HTMLFooterE = ''; + } + } else { + if ($Fhtml) { + $this->HTMLFooter = []; + $this->HTMLFooter['html'] = $Fhtml; + $this->HTMLFooter['h'] = $height; + } else { + $this->HTMLFooter = ''; + } + } + + if (!$this->mirrorMargins && $OE == 'E') { + return; + } + + if ($Fhtml == '') { + return false; + } + + if ($this->setAutoBottomMargin == 'pad') { + $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin; + $this->PageBreakTrigger = $this->h - $this->bMargin; + if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { + $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; + } + } elseif ($this->setAutoBottomMargin == 'stretch') { + $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding); + $this->PageBreakTrigger = $this->h - $this->bMargin; + if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) { + $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin; + } + } + } + + function _getHtmlHeight($html) + { + $save_state = $this->state; + if ($this->state == 0) { + $this->AddPage($this->CurOrientation); + } + $this->state = 2; + $this->Reset(); + $this->pageoutput[$this->page] = []; + $save_x = $this->x; + $save_y = $this->y; + $this->x = $this->lMargin; + $this->y = $this->margin_header; + + // Replace of page number aliases and date format + $pnstr = $this->pagenumPrefix . $this->docPageNum($this->page) . $this->pagenumSuffix; + $pntstr = $this->nbpgPrefix . $this->docPageNumTotal($this->page) . $this->nbpgSuffix; + $nb = $this->page; + $html = $this->aliasReplace($html, $pnstr, $pntstr, $nb); + + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + $savepb = $this->pageBackgrounds; + $this->writingHTMLheader = true; + $this->WriteHTML($html, HTMLParserMode::HTML_HEADER_BUFFER); + $this->writingHTMLheader = false; + $h = ($this->y - $this->margin_header); + $this->Reset(); + + // mPDF 5.7.2 - Clear in case Float used in Header/Footer + $this->blk[0]['blockContext'] = 0; + $this->blk[0]['float_endpos'] = 0; + + $this->pageoutput[$this->page] = []; + $this->headerbuffer = ''; + $this->pageBackgrounds = $savepb; + $this->x = $save_x; + $this->y = $save_y; + $this->state = $save_state; + + if ($save_state == 0) { + unset($this->pages[1]); + $this->page = 0; + } + return $h; + } + + // Called internally from Header + function writeHTMLHeaders() + { + + if ($this->mirrorMargins && ($this->page) % 2 == 0) { + $OE = 'E'; + } else { + $OE = 'O'; + } + + if ($OE === 'E') { + $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html']; + } else { + $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html']; + } + + if ($this->forcePortraitHeaders && $this->CurOrientation == 'L' && $this->CurOrientation != $this->DefOrientation) { + $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true; + $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin; + $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin; + $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header; + $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer; + $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h; + $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w; + } else { + $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin; + $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin; + $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header; + $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer; + $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w; + $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h; + } + } + + function writeHTMLFooters() + { + + if ($this->mirrorMargins && ($this->page) % 2 == 0) { + $OE = 'E'; + } else { + $OE = 'O'; + } + + if ($OE === 'E') { + $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html']; + } else { + $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooter['html']; + } + + if ($this->forcePortraitHeaders && $this->CurOrientation == 'L' && $this->CurOrientation != $this->DefOrientation) { + $this->saveHTMLFooter[$this->page][$OE]['rotate'] = true; + $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->tMargin; + $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->bMargin; + $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->rMargin; + $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->lMargin; + $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header; + $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer; + $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->h; + $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->w; + } else { + $this->saveHTMLFooter[$this->page][$OE]['ml'] = $this->lMargin; + $this->saveHTMLFooter[$this->page][$OE]['mr'] = $this->rMargin; + $this->saveHTMLFooter[$this->page][$OE]['mt'] = $this->tMargin; + $this->saveHTMLFooter[$this->page][$OE]['mb'] = $this->bMargin; + $this->saveHTMLFooter[$this->page][$OE]['mh'] = $this->margin_header; + $this->saveHTMLFooter[$this->page][$OE]['mf'] = $this->margin_footer; + $this->saveHTMLFooter[$this->page][$OE]['pw'] = $this->w; + $this->saveHTMLFooter[$this->page][$OE]['ph'] = $this->h; + } + } + + // mPDF 6 + function _shareHeaderFooterWidth($cl, $cc, $cr) + { + // mPDF 6 + $l = mb_strlen($cl, 'UTF-8'); + $c = mb_strlen($cc, 'UTF-8'); + $r = mb_strlen($cr, 'UTF-8'); + $s = max($l, $r); + $tw = $c + 2 * $s; + if ($tw > 0) { + return [intval($s * 100 / $tw), intval($c * 100 / $tw), intval($s * 100 / $tw)]; + } else { + return [33, 33, 33]; + } + } + + // mPDF 6 + // Create an HTML header/footer from array (non-HTML header/footer) + function _createHTMLheaderFooter($arr, $hf) + { + $lContent = (isset($arr['L']['content']) ? $arr['L']['content'] : ''); + $cContent = (isset($arr['C']['content']) ? $arr['C']['content'] : ''); + $rContent = (isset($arr['R']['content']) ? $arr['R']['content'] : ''); + + list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($lContent, $cContent, $rContent); + + if ($hf == 'H') { + $valign = 'bottom'; + $vpadding = '0 0 ' . $this->header_line_spacing . 'em 0'; + } else { + $valign = 'top'; + $vpadding = '' . $this->footer_line_spacing . 'em 0 0 0'; + } + + if ($this->directionality == 'rtl') { // table columns get reversed so need different text-alignment + $talignL = 'right'; + $talignR = 'left'; + } else { + $talignL = 'left'; + $talignR = 'right'; + } + + $html = '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
' . $lContent . '' . $cContent . '' . $rContent . '
'; + + return $html; + } + + function DefHeaderByName($name, $arr) + { + if (!$name) { + $name = '_nonhtmldefault'; + } + $html = $this->_createHTMLheaderFooter($arr, 'H'); + + $this->pageHTMLheaders[$name]['html'] = $html; + $this->pageHTMLheaders[$name]['h'] = $this->_getHtmlHeight($html); + } + + function DefFooterByName($name, $arr) + { + if (!$name) { + $name = '_nonhtmldefault'; + } + $html = $this->_createHTMLheaderFooter($arr, 'F'); + + $this->pageHTMLfooters[$name]['html'] = $html; + $this->pageHTMLfooters[$name]['h'] = $this->_getHtmlHeight($html); + } + + function SetHeaderByName($name, $side = 'O', $write = false) + { + if (!$name) { + $name = '_nonhtmldefault'; + } + $this->SetHTMLHeader($this->pageHTMLheaders[$name], $side, $write); + } + + function SetFooterByName($name, $side = 'O') + { + if (!$name) { + $name = '_nonhtmldefault'; + } + $this->SetHTMLFooter($this->pageHTMLfooters[$name], $side); + } + + function DefHTMLHeaderByName($name, $html) + { + if (!$name) { + $name = '_default'; + } + + $this->pageHTMLheaders[$name]['html'] = $html; + $this->pageHTMLheaders[$name]['h'] = $this->_getHtmlHeight($html); + } + + function DefHTMLFooterByName($name, $html) + { + if (!$name) { + $name = '_default'; + } + + $this->pageHTMLfooters[$name]['html'] = $html; + $this->pageHTMLfooters[$name]['h'] = $this->_getHtmlHeight($html); + } + + function SetHTMLHeaderByName($name, $side = 'O', $write = false) + { + if (!$name) { + $name = '_default'; + } + $this->SetHTMLHeader($this->pageHTMLheaders[$name], $side, $write); + } + + function SetHTMLFooterByName($name, $side = 'O') + { + if (!$name) { + $name = '_default'; + } + $this->SetHTMLFooter($this->pageHTMLfooters[$name], $side); + } + + function SetHeader($Harray = [], $side = '', $write = false) + { + $oddhtml = ''; + $evenhtml = ''; + + if (is_string($Harray)) { + + if (strlen($Harray) === 0) { + + $oddhtml = ''; + $evenhtml = ''; + + } elseif (strpos($Harray, '|') !== false) { + + $hdet = explode('|', $Harray); + + list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($hdet[0], $hdet[1], $hdet[2]); + $oddhtml = ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= '
' . $hdet[0] . '' . $hdet[1] . '' . $hdet[2] . '
'; + + $evenhtml = ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= '
' . $hdet[2] . '' . $hdet[1] . '' . $hdet[0] . '
'; + + } else { + + $oddhtml = '
' . $Harray . '
'; + $evenhtml = '
' . $Harray . '
'; + } + + } elseif (is_array($Harray) && !empty($Harray)) { + + $odd = null; + $even = null; + + if ($side === 'O') { + $odd = $Harray; + } elseif ($side === 'E') { + $even = $Harray; + } else { + $odd = Arrays::get($Harray, 'odd', null); + $even = Arrays::get($Harray, 'even', null); + } + + $oddhtml = $this->_createHTMLheaderFooter($odd, 'H'); + $evenhtml = $this->_createHTMLheaderFooter($even, 'H'); + } + + if ($side === 'E') { + $this->SetHTMLHeader($evenhtml, 'E', $write); + } elseif ($side === 'O') { + $this->SetHTMLHeader($oddhtml, 'O', $write); + } else { + $this->SetHTMLHeader($oddhtml, 'O', $write); + $this->SetHTMLHeader($evenhtml, 'E', $write); + } + } + + function SetFooter($Farray = [], $side = '') + { + $oddhtml = ''; + $evenhtml = ''; + + if (is_string($Farray)) { + + if (strlen($Farray) == 0) { + + $oddhtml = ''; + $evenhtml = ''; + + } elseif (strpos($Farray, '|') !== false) { + + $hdet = explode('|', $Farray); + $oddhtml = ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= ''; + $oddhtml .= '
' . $hdet[0] . '' . $hdet[1] . '' . $hdet[2] . '
'; + + $evenhtml = ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= ''; + $evenhtml .= '
' . $hdet[2] . '' . $hdet[1] . '' . $hdet[0] . '
'; + + } else { + + $oddhtml = '
' . $Farray . '
'; + + $evenhtml = '
' . $Farray . '
'; + } + + } elseif (is_array($Farray)) { + + $odd = null; + $even = null; + + if ($side === 'O') { + $odd = $Farray; + } elseif ($side == 'E') { + $even = $Farray; + } else { + $odd = Arrays::get($Farray, 'odd', null); + $even = Arrays::get($Farray, 'even', null); + } + + $oddhtml = $this->_createHTMLheaderFooter($odd, 'F'); + $evenhtml = $this->_createHTMLheaderFooter($even, 'F'); + } + + if ($side === 'E') { + $this->SetHTMLFooter($evenhtml, 'E'); + } elseif ($side === 'O') { + $this->SetHTMLFooter($oddhtml, 'O'); + } else { + $this->SetHTMLFooter($oddhtml, 'O'); + $this->SetHTMLFooter($evenhtml, 'E'); + } + } + + /* -- WATERMARK -- */ + + function SetWatermarkText($txt = '', $alpha = -1) + { + if ($txt instanceof \Mpdf\WatermarkText) { + $this->watermarkTextObject = $txt; + $this->watermarkText = $txt->getText(); + $this->watermarkTextAlpha = $txt->getAlpha(); + $this->watermarkAngle = $txt->getAngle(); + $this->watermark_font = $txt->getFont() === null ? $txt->getFont() : $this->watermark_font; + $this->watermark_size = $txt->getSize(); + + return; + } + + if ($alpha >= 0) { + $this->watermarkTextAlpha = $alpha; + } + + $this->watermarkText = $txt; + } + + function SetWatermarkImage($src, $alpha = -1, $size = 'D', $pos = 'F') + { + if ($src instanceof \Mpdf\WatermarkImage) { + $this->watermarkImage = $src->getPath(); + $this->watermark_size = $src->getSize(); + $this->watermark_pos = $src->getPosition(); + $this->watermarkImageAlpha = $src->getAlpha(); + $this->watermarkImgBehind = $src->isBehindContent(); + $this->watermarkImgAlphaBlend = $src->getAlphaBlend(); + + return; + } + + if ($alpha >= 0) { + $this->watermarkImageAlpha = $alpha; + } + + $this->watermarkImage = $src; + $this->watermark_size = $size; + $this->watermark_pos = $pos; + } + + /* -- END WATERMARK -- */ + + // Page footer + function Footer() + { + /* -- CSS-PAGE -- */ + // PAGED MEDIA - CROP / CROSS MARKS from @PAGE + if ($this->show_marks == 'CROP' || $this->show_marks == 'CROPCROSS') { + // Show TICK MARKS + $this->SetLineWidth(0.1); // = 0.1 mm + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $l = $this->cropMarkLength; + $m = $this->cropMarkMargin; // Distance of crop mark from margin + $b = $this->nonPrintMargin; // Non-printable border at edge of paper sheet + $ax1 = $b; + $bx = $this->page_box['outer_width_LR'] - $m; + $ax = max($ax1, $bx - $l); + $cx1 = $this->w - $b; + $dx = $this->w - $this->page_box['outer_width_LR'] + $m; + $cx = min($cx1, $dx + $l); + $ay1 = $b; + $by = $this->page_box['outer_width_TB'] - $m; + $ay = max($ay1, $by - $l); + $cy1 = $this->h - $b; + $dy = $this->h - $this->page_box['outer_width_TB'] + $m; + $cy = min($cy1, $dy + $l); + + $this->Line($ax, $this->page_box['outer_width_TB'], $bx, $this->page_box['outer_width_TB']); + $this->Line($cx, $this->page_box['outer_width_TB'], $dx, $this->page_box['outer_width_TB']); + $this->Line($ax, $this->h - $this->page_box['outer_width_TB'], $bx, $this->h - $this->page_box['outer_width_TB']); + $this->Line($cx, $this->h - $this->page_box['outer_width_TB'], $dx, $this->h - $this->page_box['outer_width_TB']); + $this->Line($this->page_box['outer_width_LR'], $ay, $this->page_box['outer_width_LR'], $by); + $this->Line($this->page_box['outer_width_LR'], $cy, $this->page_box['outer_width_LR'], $dy); + $this->Line($this->w - $this->page_box['outer_width_LR'], $ay, $this->w - $this->page_box['outer_width_LR'], $by); + $this->Line($this->w - $this->page_box['outer_width_LR'], $cy, $this->w - $this->page_box['outer_width_LR'], $dy); + + if ($this->printers_info) { + $hd = date('Y-m-d H:i') . ' Page ' . $this->page . ' of {nb}'; + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetFont('arial', '', 7.5, true, true); + $this->x = $this->page_box['outer_width_LR'] + 1.5; + $this->y = 1; + $this->Cell(0, $this->FontSize, $hd, 0, 0, 'L', 0, '', 0, 0, 0, 'M'); + $this->SetFont($this->default_font, '', $this->original_default_font_size); + } + } + if ($this->show_marks == 'CROSS' || $this->show_marks == 'CROPCROSS') { + $this->SetLineWidth(0.1); // = 0.1 mm + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $l = 14 / 2; // longer length of the cross line (half) + $w = 6 / 2; // shorter width of the cross line (half) + $r = 1.2; // radius of circle + $m = $this->crossMarkMargin; // Distance of cross mark from margin + $x1 = $this->page_box['outer_width_LR'] - $m; + $x2 = $this->w - $this->page_box['outer_width_LR'] + $m; + $y1 = $this->page_box['outer_width_TB'] - $m; + $y2 = $this->h - $this->page_box['outer_width_TB'] + $m; + // Left + $this->Circle($x1, $this->h / 2, $r, 'S'); + $this->Line($x1 - $w, $this->h / 2, $x1 + $w, $this->h / 2); + $this->Line($x1, $this->h / 2 - $l, $x1, $this->h / 2 + $l); + // Right + $this->Circle($x2, $this->h / 2, $r, 'S'); + $this->Line($x2 - $w, $this->h / 2, $x2 + $w, $this->h / 2); + $this->Line($x2, $this->h / 2 - $l, $x2, $this->h / 2 + $l); + // Top + $this->Circle($this->w / 2, $y1, $r, 'S'); + $this->Line($this->w / 2, $y1 - $w, $this->w / 2, $y1 + $w); + $this->Line($this->w / 2 - $l, $y1, $this->w / 2 + $l, $y1); + // Bottom + $this->Circle($this->w / 2, $y2, $r, 'S'); + $this->Line($this->w / 2, $y2 - $w, $this->w / 2, $y2 + $w); + $this->Line($this->w / 2 - $l, $y2, $this->w / 2 + $l, $y2); + } + + /* -- END CSS-PAGE -- */ + + // mPDF 6 + // If @page set non-HTML headers/footers named, they were not read until later in the HTML code - so now set them + if ($this->page == 1) { + if ($this->firstPageBoxHeader) { + if (isset($this->pageHTMLheaders[$this->firstPageBoxHeader])) { + $this->HTMLHeader = $this->pageHTMLheaders[$this->firstPageBoxHeader]; + } + $this->Header(); + } + if ($this->firstPageBoxFooter) { + if (isset($this->pageHTMLfooters[$this->firstPageBoxFooter])) { + $this->HTMLFooter = $this->pageHTMLfooters[$this->firstPageBoxFooter]; + } + } + $this->firstPageBoxHeader = ''; + $this->firstPageBoxFooter = ''; + } + + + if (($this->mirrorMargins && ($this->page % 2 == 0) && $this->HTMLFooterE) || ($this->mirrorMargins && ($this->page % 2 == 1) && $this->HTMLFooter) || (!$this->mirrorMargins && $this->HTMLFooter)) { + $this->writeHTMLFooters(); + } + + /* -- WATERMARK -- */ + if (($this->watermarkText) && ($this->showWatermarkText)) { + $this->watermark($this->watermarkText, $this->watermarkAngle, is_int($this->watermark_size) ? $this->watermark_size : 120, $this->watermarkTextAlpha); // Watermark text + } + if (($this->watermarkImage) && ($this->showWatermarkImage)) { + $this->watermarkImg($this->watermarkImage, $this->watermarkImageAlpha); // Watermark image + } + /* -- END WATERMARK -- */ + } + + /* -- HTML-CSS -- */ + + /** + * Write HTML code to the document + * + * Also used internally to parse HTML into buffers + * + * @param string $html + * @param int $mode Use HTMLParserMode constants. Controls what parts of the $html code is parsed. + * @param bool $init Clears and sets buffers to Top level block etc. + * @param bool $close If false leaves buffers etc. in current state, so that it can continue a block etc. + */ + function WriteHTML($html, $mode = HTMLParserMode::DEFAULT_MODE, $init = true, $close = true) + { + /* Check $html is an integer, float, string, boolean or class with __toString(), otherwise throw exception */ + if (is_scalar($html) === false) { + if (!is_object($html) || ! method_exists($html, '__toString')) { + throw new \Mpdf\MpdfException('WriteHTML() requires $html be an integer, float, string, boolean or an object with the __toString() magic method.'); + } + } + + // Check the mode is valid + if (in_array($mode, HTMLParserMode::getAllModes(), true) === false) { + throw new \Mpdf\MpdfException('WriteHTML() requires $mode to be one of the modes defined in HTMLParserMode'); + } + + /* Cast $html as a string */ + $html = (string) $html; + + // @log Parsing CSS & Headers + + if ($init) { + $this->headerbuffer = ''; + $this->textbuffer = []; + $this->fixedPosBlockSave = []; + } + if ($mode === HTMLParserMode::HEADER_CSS) { + $html = ''; + } // stylesheet only + + if ($this->allow_charset_conversion) { + if ($mode === HTMLParserMode::DEFAULT_MODE) { + $this->ReadCharset($html); + } + if ($this->charset_in && $mode !== HTMLParserMode::HTML_HEADER_BUFFER) { + $success = iconv($this->charset_in, 'UTF-8//TRANSLIT', $html); + if ($success) { + $html = $success; + } + } + } + + $html = $this->purify_utf8($html, false); + if ($init) { + $this->blklvl = 0; + $this->lastblocklevelchange = 0; + $this->blk = []; + $this->initialiseBlock($this->blk[0]); + $this->blk[0]['width'] = & $this->pgwidth; + $this->blk[0]['inner_width'] = & $this->pgwidth; + $this->blk[0]['blockContext'] = $this->blockContext; + } + + $zproperties = []; + if ($mode === HTMLParserMode::DEFAULT_MODE || $mode === HTMLParserMode::HEADER_CSS) { + $this->ReadMetaTags($html); + + if (preg_match('/]*href=["\']([^"\'>]*)["\']/i', $html, $m)) { + $this->SetBasePath($m[1]); + } + $html = $this->cssManager->ReadCSS($html); + + if ($this->autoLangToFont && !$this->usingCoreFont && preg_match('/]*lang=[\'\"](.*?)[\'\"]/ism', $html, $m)) { + $html_lang = $m[1]; + } + + if (preg_match('/]*dir=[\'\"]\s*rtl\s*[\'\"]/ism', $html)) { + $zproperties['DIRECTION'] = 'rtl'; + } + + // allow in-line CSS for body tag to be parsed // Get tag inline CSS + if (preg_match('/]*)>(.*?)<\/body>/ism', $html, $m) || preg_match('/]*)>(.*)$/ism', $html, $m)) { + $html = $m[2]; + // Changed to allow style="background: url('bg.jpg')" + if (preg_match('/style=[\"](.*?)[\"]/ism', $m[1], $mm) || preg_match('/style=[\'](.*?)[\']/ism', $m[1], $mm)) { + $zproperties = $this->cssManager->readInlineCSS($mm[1]); + } + if (preg_match('/dir=[\'\"]\s*rtl\s*[\'\"]/ism', $m[1])) { + $zproperties['DIRECTION'] = 'rtl'; + } + if (isset($html_lang) && $html_lang) { + $zproperties['LANG'] = $html_lang; + } + if ($this->autoLangToFont && !$this->onlyCoreFonts && preg_match('/lang=[\'\"](.*?)[\'\"]/ism', $m[1], $mm)) { + $zproperties['LANG'] = $mm[1]; + } + } + } + $properties = $this->cssManager->MergeCSS('BLOCK', 'BODY', ''); + if ($zproperties) { + $properties = $this->cssManager->array_merge_recursive_unique($properties, $zproperties); + } + + if (isset($properties['DIRECTION']) && $properties['DIRECTION']) { + $this->cssManager->CSS['BODY']['DIRECTION'] = $properties['DIRECTION']; + } + if (!isset($this->cssManager->CSS['BODY']['DIRECTION'])) { + $this->cssManager->CSS['BODY']['DIRECTION'] = $this->directionality; + } else { + $this->SetDirectionality($this->cssManager->CSS['BODY']['DIRECTION']); + } + + $this->setCSS($properties, '', 'BODY'); + + $this->blk[0]['InlineProperties'] = $this->saveInlineProperties(); + + if ($mode === HTMLParserMode::HEADER_CSS) { + return ''; + } + if (!isset($this->cssManager->CSS['BODY'])) { + $this->cssManager->CSS['BODY'] = []; + } + + /* -- BACKGROUNDS -- */ + if (isset($properties['BACKGROUND-GRADIENT'])) { + $this->bodyBackgroundGradient = $properties['BACKGROUND-GRADIENT']; + } + + if (isset($properties['BACKGROUND-IMAGE']) && $properties['BACKGROUND-IMAGE']) { + $ret = $this->SetBackground($properties, $this->pgwidth); + if ($ret) { + $this->bodyBackgroundImage = $ret; + } + } + /* -- END BACKGROUNDS -- */ + + /* -- CSS-PAGE -- */ + // If page-box is set + if ($this->state == 0 && ((isset($this->cssManager->CSS['@PAGE']) && $this->cssManager->CSS['@PAGE']) || (isset($this->cssManager->CSS['@PAGE>>PSEUDO>>FIRST']) && $this->cssManager->CSS['@PAGE>>PSEUDO>>FIRST']))) { // mPDF 5.7.3 + $this->page_box['current'] = ''; + $this->page_box['using'] = true; + list($pborientation, $pbmgl, $pbmgr, $pbmgt, $pbmgb, $pbmgh, $pbmgf, $hname, $fname, $bg, $resetpagenum, $pagenumstyle, $suppress, $marks, $newformat) = $this->SetPagedMediaCSS('', false, 'O'); + $this->DefOrientation = $this->CurOrientation = $pborientation; + $this->orig_lMargin = $this->DeflMargin = $pbmgl; + $this->orig_rMargin = $this->DefrMargin = $pbmgr; + $this->orig_tMargin = $this->tMargin = $pbmgt; + $this->orig_bMargin = $this->bMargin = $pbmgb; + $this->orig_hMargin = $this->margin_header = $pbmgh; + $this->orig_fMargin = $this->margin_footer = $pbmgf; + list($pborientation, $pbmgl, $pbmgr, $pbmgt, $pbmgb, $pbmgh, $pbmgf, $hname, $fname, $bg, $resetpagenum, $pagenumstyle, $suppress, $marks, $newformat) = $this->SetPagedMediaCSS('', true, 'O'); // first page + $this->show_marks = $marks; + if ($hname) { + $this->firstPageBoxHeader = $hname; + } + if ($fname) { + $this->firstPageBoxFooter = $fname; + } + } + /* -- END CSS-PAGE -- */ + + $parseonly = false; + $this->bufferoutput = false; + if ($mode == HTMLParserMode::HTML_PARSE_NO_WRITE) { + $parseonly = true; + // Close any open block tags + $arr = []; + $ai = 0; + for ($b = $this->blklvl; $b > 0; $b--) { + $this->tag->CloseTag($this->blk[$b]['tag'], $arr, $ai); + } + // Output any text left in buffer + if (count($this->textbuffer)) { + $this->printbuffer($this->textbuffer); + } + $this->textbuffer = []; + } elseif ($mode === HTMLParserMode::HTML_HEADER_BUFFER) { + // Close any open block tags + $arr = []; + $ai = 0; + for ($b = $this->blklvl; $b > 0; $b--) { + $this->tag->CloseTag($this->blk[$b]['tag'], $arr, $ai); + } + // Output any text left in buffer + if (count($this->textbuffer)) { + $this->printbuffer($this->textbuffer); + } + $this->bufferoutput = true; + $this->textbuffer = []; + $this->headerbuffer = ''; + $properties = $this->cssManager->MergeCSS('BLOCK', 'BODY', ''); + $this->setCSS($properties, '', 'BODY'); + } + + mb_internal_encoding('UTF-8'); + + $html = $this->AdjustHTML($html, $this->tabSpaces); // Try to make HTML look more like XHTML + + if ($this->autoScriptToLang) { + $html = $this->markScriptToLang($html); + } + + preg_match_all('/]*)>(.*?)<\/htmlpageheader>/si', $html, $h); + for ($i = 0; $i < count($h[1]); $i++) { + if (preg_match('/name=[\'|\"](.*?)[\'|\"]/', $h[1][$i], $n)) { + $this->pageHTMLheaders[$n[1]]['html'] = $h[2][$i]; + $this->pageHTMLheaders[$n[1]]['h'] = $this->_getHtmlHeight($h[2][$i]); + } + } + preg_match_all('/]*)>(.*?)<\/htmlpagefooter>/si', $html, $f); + for ($i = 0; $i < count($f[1]); $i++) { + if (preg_match('/name=[\'|\"](.*?)[\'|\"]/', $f[1][$i], $n)) { + $this->pageHTMLfooters[$n[1]]['html'] = $f[2][$i]; + $this->pageHTMLfooters[$n[1]]['h'] = $this->_getHtmlHeight($f[2][$i]); + } + } + + $html = preg_replace('//si', '', $html); + $html = preg_replace('//si', '', $html); + + if ($this->state == 0 && ($mode === HTMLParserMode::DEFAULT_MODE || $mode === HTMLParserMode::HTML_BODY)) { + $this->AddPage($this->CurOrientation); + } + + + if (isset($hname) && preg_match('/^html_(.*)$/i', $hname, $n)) { + $this->SetHTMLHeader($this->pageHTMLheaders[$n[1]], 'O', true); + } + if (isset($fname) && preg_match('/^html_(.*)$/i', $fname, $n)) { + $this->SetHTMLFooter($this->pageHTMLfooters[$n[1]], 'O'); + } + + + + $html = str_replace('checkSIP = false; + $this->checkSMP = false; + $this->checkCJK = false; + if ($this->onlyCoreFonts) { + $html = $this->SubstituteChars($html); + } else { + if (preg_match("/([" . $this->pregRTLchars . "])/u", $html)) { + $this->biDirectional = true; + } // *OTL* + if (preg_match("/([\x{20000}-\x{2FFFF}])/u", $html)) { + $this->checkSIP = true; + } + if (preg_match("/([\x{10000}-\x{1FFFF}])/u", $html)) { + $this->checkSMP = true; + } + /* -- CJK-FONTS -- */ + if (preg_match("/([" . $this->pregCJKchars . "])/u", $html)) { + $this->checkCJK = true; + } + /* -- END CJK-FONTS -- */ + } + + // Don't allow non-breaking spaces that are converted to substituted chars or will break anyway and mess up table width calc. + $html = str_replace('160', chr(32), $html); + $html = str_replace('', '|', $html); + $html = str_replace('', '|', $html); + $html = str_replace('', '|', $html); + + // Add new supported tags in the DisableTags function + $html = strip_tags($html, $this->enabledtags); // remove all unsupported tags, but the ones inside the 'enabledtags' string + // Explode the string in order to parse the HTML code + $a = preg_split('/<(.*?)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE); + // ? more accurate regexp that allows e.g.
+ // if changing - also change in fn.SubstituteChars() + // $a = preg_split ('/<((?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE); + + if ($this->mb_enc) { + mb_internal_encoding($this->mb_enc); + } + $pbc = 0; + $this->subPos = -1; + $cnt = count($a); + for ($i = 0; $i < $cnt; $i++) { + $e = $a[$i]; + if ($i % 2 == 0) { + // TEXT + if ($this->blk[$this->blklvl]['hide']) { + continue; + } + if ($this->inlineDisplayOff) { + continue; + } + if ($this->inMeter) { + continue; + } + + if ($this->inFixedPosBlock) { + $this->fixedPosBlock .= $e; + continue; + } // *CSS-POSITION* + if (strlen($e) == 0) { + continue; + } + + if ($this->ignorefollowingspaces && !$this->ispre) { + if (strlen(ltrim($e)) == 0) { + continue; + } + if ($this->FontFamily != 'csymbol' && $this->FontFamily != 'czapfdingbats' && substr($e, 0, 1) == ' ') { + $this->ignorefollowingspaces = false; + $e = ltrim($e); + } + } + + $this->OTLdata = null; // mPDF 5.7.1 + + $e = UtfString::strcode2utf($e); + $e = $this->lesser_entity_decode($e); + + if ($this->usingCoreFont) { + // If core font is selected in document which is not onlyCoreFonts - substitute with non-core font + if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->subPos < $i && !$this->specialcontent) { + $cnt += $this->SubstituteCharsNonCore($a, $i, $e); + } + // CONVERT ENCODING + $e = mb_convert_encoding($e, $this->mb_enc, 'UTF-8'); + if ($this->textvar & TextVars::FT_UPPERCASE) { + $e = mb_strtoupper($e, $this->mb_enc); + } // mPDF 5.7.1 + elseif ($this->textvar & TextVars::FT_LOWERCASE) { + $e = mb_strtolower($e, $this->mb_enc); + } // mPDF 5.7.1 + elseif ($this->textvar & TextVars::FT_CAPITALIZE) { + $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); + } // mPDF 5.7.1 + } else { + if ($this->checkSIP && $this->CurrentFont['sipext'] && $this->subPos < $i && (!$this->specialcontent || !$this->useActiveForms)) { + $cnt += $this->SubstituteCharsSIP($a, $i, $e); + } + + if ($this->useSubstitutions && !$this->onlyCoreFonts && $this->CurrentFont['type'] != 'Type0' && $this->subPos < $i && (!$this->specialcontent || !$this->useActiveForms)) { + $cnt += $this->SubstituteCharsMB($a, $i, $e); + } + + if ($this->textvar & TextVars::FT_UPPERCASE) { + $e = mb_strtoupper($e, $this->mb_enc); + } elseif ($this->textvar & TextVars::FT_LOWERCASE) { + $e = mb_strtolower($e, $this->mb_enc); + } elseif ($this->textvar & TextVars::FT_CAPITALIZE) { + $e = mb_convert_case($e, MB_CASE_TITLE, "UTF-8"); + } + + /* -- OTL -- */ + // Use OTL OpenType Table Layout - GSUB & GPOS + if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL'] && (!$this->specialcontent || !$this->useActiveForms)) { + if (!$this->otl) { + $this->otl = new Otl($this, $this->fontCache); + } + $e = $this->otl->applyOTL($e, $this->CurrentFont['useOTL']); + $this->OTLdata = $this->otl->OTLdata; + $this->otl->removeChar($e, $this->OTLdata, "\xef\xbb\xbf"); // Remove ZWNBSP (also Byte order mark FEFF) + } /* -- END OTL -- */ + else { + // removes U+200E/U+200F LTR and RTL mark and U+200C/U+200D Zero-width Joiner and Non-joiner + $e = preg_replace("/[\xe2\x80\x8c\xe2\x80\x8d\xe2\x80\x8e\xe2\x80\x8f]/u", '', $e); + $e = preg_replace("/[\xef\xbb\xbf]/u", '', $e); // Remove ZWNBSP (also Byte order mark FEFF) + } + } + + if (($this->tts) || ($this->ttz) || ($this->tta)) { + $es = explode('|', $e); + $e = ''; + foreach ($es as $val) { + $e .= chr($val); + } + } + + // FORM ELEMENTS + if ($this->specialcontent) { + /* -- FORMS -- */ + // SELECT tag (form element) + if ($this->specialcontent == "type=select") { + $e = ltrim($e); + if (!empty($this->OTLdata)) { + $this->otl->trimOTLdata($this->OTLdata, true, false); + } // *OTL* + $stringwidth = $this->GetStringWidth($e); + if (!isset($this->selectoption['MAXWIDTH']) || $stringwidth > $this->selectoption['MAXWIDTH']) { + $this->selectoption['MAXWIDTH'] = $stringwidth; + } + if (!isset($this->selectoption['SELECTED']) || $this->selectoption['SELECTED'] == '') { + $this->selectoption['SELECTED'] = $e; + if (!empty($this->OTLdata)) { + $this->selectoption['SELECTED-OTLDATA'] = $this->OTLdata; + } // *OTL* + } + // Active Forms + if (isset($this->selectoption['ACTIVE']) && $this->selectoption['ACTIVE']) { + $this->selectoption['ITEMS'][] = ['exportValue' => $this->selectoption['currentVAL'], 'content' => $e, 'selected' => $this->selectoption['currentSEL']]; + } + $this->OTLdata = []; + } // TEXTAREA + else { + $objattr = unserialize($this->specialcontent); + $objattr['text'] = $e; + $objattr['OTLdata'] = $this->OTLdata; + $this->OTLdata = []; + $te = Mpdf::OBJECT_IDENTIFIER . "type=textarea,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->tdbegin) { + $this->_saveCellTextBuffer($te, $this->HREF); + } else { + $this->_saveTextBuffer($te, $this->HREF); + } + } + /* -- END FORMS -- */ + } // TABLE + elseif ($this->tableLevel) { + /* -- TABLES -- */ + if ($this->tdbegin) { + if (($this->ignorefollowingspaces) && !$this->ispre) { + $e = ltrim($e); + if (!empty($this->OTLdata)) { + $this->otl->trimOTLdata($this->OTLdata, true, false); + } // *OTL* + } + if ($e || $e === '0') { + if ($this->blockjustfinished && $this->cell[$this->row][$this->col]['s'] > 0) { + $this->_saveCellTextBuffer("\n"); + if (!isset($this->cell[$this->row][$this->col]['maxs'])) { + $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s']; + } elseif ($this->cell[$this->row][$this->col]['maxs'] < $this->cell[$this->row][$this->col]['s']) { + $this->cell[$this->row][$this->col]['maxs'] = $this->cell[$this->row][$this->col]['s']; + } + $this->cell[$this->row][$this->col]['s'] = 0; // reset + } + $this->blockjustfinished = false; + + if (!isset($this->cell[$this->row][$this->col]['R']) || !$this->cell[$this->row][$this->col]['R']) { + if (isset($this->cell[$this->row][$this->col]['s'])) { + $this->cell[$this->row][$this->col]['s'] += $this->GetStringWidth($e, false, $this->OTLdata, $this->textvar); + } else { + $this->cell[$this->row][$this->col]['s'] = $this->GetStringWidth($e, false, $this->OTLdata, $this->textvar); + } + if (!empty($this->spanborddet)) { + $this->cell[$this->row][$this->col]['s'] += (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0) + (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0); + } + } + + $this->_saveCellTextBuffer($e, $this->HREF); + + if (substr($this->cell[$this->row][$this->col]['a'], 0, 1) == 'D') { + + $dp = $this->decimal_align[substr($this->cell[$this->row][$this->col]['a'], 0, 2)]; + $s = preg_split('/' . preg_quote($dp, '/') . '/', $e, 2); // ? needs to be /u if not core + $s0 = $this->GetStringWidth($s[0], false); + + if (isset($s[1]) && $s[1]) { + $s1 = $this->GetStringWidth(($s[1] . $dp), false); + } else { + $s1 = 0; + } + + if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'])) { + if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'] === false) { + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'] = []; + } + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = $s0; + } else { + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = max($s0, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0']); + } + + if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'])) { + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = $s1; + } else { + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = max($s1, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1']); + } + } + + $this->nestedtablejustfinished = false; + $this->linebreakjustfinished = false; + } + } + /* -- END TABLES -- */ + } // ALL ELSE + else { + if ($this->ignorefollowingspaces && !$this->ispre) { + $e = ltrim($e); + if (!empty($this->OTLdata)) { + $this->otl->trimOTLdata($this->OTLdata, true, false); + } // *OTL* + } + if ($e || $e === '0') { + $this->_saveTextBuffer($e, $this->HREF); + } + } + if ($e || $e === '0') { + $this->ignorefollowingspaces = false; // mPDF 6 + } + if (substr($e, -1, 1) == ' ' && !$this->ispre && $this->FontFamily != 'csymbol' && $this->FontFamily != 'czapfdingbats') { + $this->ignorefollowingspaces = true; + } + } else { // TAG ** + if (isset($e[0]) && $e[0] == '/') { + $endtag = trim(strtoupper(substr($e, 1))); + + /* -- CSS-POSITION -- */ + // mPDF 6 + if ($this->inFixedPosBlock) { + if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) { + $this->fixedPosBlockDepth--; + } + if ($this->fixedPosBlockDepth == 0) { + $this->fixedPosBlockSave[] = [$this->fixedPosBlock, $this->fixedPosBlockBBox, $this->page]; + $this->fixedPosBlock = ''; + $this->inFixedPosBlock = false; + continue; + } + $this->fixedPosBlock .= '<' . $e . '>'; + continue; + } + /* -- END CSS-POSITION -- */ + + // mPDF 6 + // Correct for tags where HTML5 specifies optional end tags (see also OpenTag() ) + if ($this->allow_html_optional_endtags && !$parseonly) { + if (isset($this->blk[$this->blklvl]['tag'])) { + $closed = false; + // li end tag may be omitted if there is no more content in the parent element + if (!$closed && $this->blk[$this->blklvl]['tag'] == 'LI' && $endtag != 'LI' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { + $this->tag->CloseTag('LI', $a, $i); + $closed = true; + } + // dd end tag may be omitted if there is no more content in the parent element + if (!$closed && $this->blk[$this->blklvl]['tag'] == 'DD' && $endtag != 'DD' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { + $this->tag->CloseTag('DD', $a, $i); + $closed = true; + } + // p end tag may be omitted if there is no more content in the parent element and the parent element is not an A element [??????] + if (!$closed && $this->blk[$this->blklvl]['tag'] == 'P' && $endtag != 'P' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { + $this->tag->CloseTag('P', $a, $i); + $closed = true; + } + // option end tag may be omitted if there is no more content in the parent element + if (!$closed && $this->blk[$this->blklvl]['tag'] == 'OPTION' && $endtag != 'OPTION' && (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags))) { + $this->tag->CloseTag('OPTION', $a, $i); + $closed = true; + } + } + /* -- TABLES -- */ + // Check for Table tags where HTML specifies optional end tags, + if ($endtag == 'TABLE') { + if ($this->lastoptionaltag == 'THEAD' || $this->lastoptionaltag == 'TBODY' || $this->lastoptionaltag == 'TFOOT') { + $this->tag->CloseTag($this->lastoptionaltag, $a, $i); + } + if ($this->lastoptionaltag == 'TR') { + $this->tag->CloseTag('TR', $a, $i); + } + if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { + $this->tag->CloseTag($this->lastoptionaltag, $a, $i); + $this->tag->CloseTag('TR', $a, $i); + } + } + if ($endtag == 'THEAD' || $endtag == 'TBODY' || $endtag == 'TFOOT') { + if ($this->lastoptionaltag == 'TR') { + $this->tag->CloseTag('TR', $a, $i); + } + if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { + $this->tag->CloseTag($this->lastoptionaltag, $a, $i); + $this->tag->CloseTag('TR', $a, $i); + } + } + if ($endtag == 'TR') { + if ($this->lastoptionaltag == 'TD' || $this->lastoptionaltag == 'TH') { + $this->tag->CloseTag($this->lastoptionaltag, $a, $i); + } + } + /* -- END TABLES -- */ + } + + + // mPDF 6 + if ($this->blk[$this->blklvl]['hide']) { + if (in_array($endtag, $this->outerblocktags) || in_array($endtag, $this->innerblocktags)) { + unset($this->blk[$this->blklvl]); + $this->blklvl--; + } + continue; + } + + // mPDF 6 + $this->tag->CloseTag($endtag, $a, $i); // mPDF 6 + } else { // OPENING TAG + if ($this->blk[$this->blklvl]['hide']) { + if (strpos($e, ' ')) { + $te = strtoupper(substr($e, 0, strpos($e, ' '))); + } else { + $te = strtoupper($e); + } + // mPDF 6 + if ($te == 'THEAD' || $te == 'TBODY' || $te == 'TFOOT' || $te == 'TR' || $te == 'TD' || $te == 'TH') { + $this->lastoptionaltag = $te; + } + if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) { + $this->blklvl++; + $this->blk[$this->blklvl]['hide'] = true; + $this->blk[$this->blklvl]['tag'] = $te; // mPDF 6 + } + continue; + } + + /* -- CSS-POSITION -- */ + if ($this->inFixedPosBlock) { + if (strpos($e, ' ')) { + $te = strtoupper(substr($e, 0, strpos($e, ' '))); + } else { + $te = strtoupper($e); + } + $this->fixedPosBlock .= '<' . $e . '>'; + if (in_array($te, $this->outerblocktags) || in_array($te, $this->innerblocktags)) { + $this->fixedPosBlockDepth++; + } + continue; + } + /* -- END CSS-POSITION -- */ + $regexp = '|=\'(.*?)\'|s'; // eliminate single quotes, if any + $e = preg_replace($regexp, "=\"\$1\"", $e); + // changes anykey=anyvalue to anykey="anyvalue" (only do this inside [some] tags) + if (substr($e, 0, 10) != 'pageheader' && substr($e, 0, 10) != 'pagefooter' && substr($e, 0, 12) != 'tocpagebreak' && substr($e, 0, 10) != 'indexentry' && substr($e, 0, 8) != 'tocentry') { // mPDF 6 (ZZZ99H) + $regexp = '| (\\w+?)=([^\\s>"]+)|si'; + $e = preg_replace($regexp, " \$1=\"\$2\"", $e); + } + + $e = preg_replace('/ (\\S+?)\s*=\s*"/i', " \\1=\"", $e); + + // Fix path values, if needed + $orig_srcpath = ''; + if ((stristr($e, "href=") !== false) or ( stristr($e, "src=") !== false)) { + $regexp = '/ (href|src)\s*=\s*"(.*?)"/i'; + preg_match($regexp, $e, $auxiliararray); + if (isset($auxiliararray[2])) { + $path = $auxiliararray[2]; + } else { + $path = ''; + } + if (trim($path) != '' && !(stristr($e, "src=") !== false && substr($path, 0, 4) == 'var:') && substr($path, 0, 1) != '@') { + $path = htmlspecialchars_decode($path); // mPDF 5.7.4 URLs + $orig_srcpath = $path; + $this->GetFullPath($path); + $regexp = '/ (href|src)="(.*?)"/i'; + $e = preg_replace($regexp, ' \\1="' . $path . '"', $e); + } + }//END of Fix path values + // Extract attributes + $contents = []; + $contents1 = []; + $contents2 = []; + // Changed to allow style="background: url('bg.jpg')" + // Changed to improve performance; maximum length of \S (attribute) = 16 + // Increase allowed attribute name to 32 - cutting off "toc-even-header-name" etc. + preg_match_all('/\\S{1,32}=["][^"]*["]/', $e, $contents1); + preg_match_all('/\\S{1,32}=[\'][^\']*[\']/i', $e, $contents2); + + $contents = array_merge($contents1, $contents2); + preg_match('/\\S+/', $e, $a2); + $tag = (isset($a2[0]) ? strtoupper($a2[0]) : ''); + $attr = []; + if ($orig_srcpath) { + $attr['ORIG_SRC'] = $orig_srcpath; + } + if (!empty($contents)) { + foreach ($contents[0] as $v) { + // Changed to allow style="background: url('bg.jpg')" + if (preg_match('/^([^=]*)=["]?([^"]*)["]?$/', $v, $a3) || preg_match('/^([^=]*)=[\']?([^\']*)[\']?$/', $v, $a3)) { + if (strtoupper($a3[1]) == 'ID' || strtoupper($a3[1]) == 'CLASS') { // 4.2.013 Omits STYLE + $attr[strtoupper($a3[1])] = trim(strtoupper($a3[2])); + } // includes header-style-right etc. used for + elseif (preg_match('/^(HEADER|FOOTER)-STYLE/i', $a3[1])) { + $attr[strtoupper($a3[1])] = trim(strtoupper($a3[2])); + } else { + $attr[strtoupper($a3[1])] = trim($a3[2]); + } + } + } + } + $this->tag->OpenTag($tag, $attr, $a, $i); // mPDF 6 + /* -- CSS-POSITION -- */ + if ($this->inFixedPosBlock) { + $this->fixedPosBlockBBox = [$tag, $attr, $this->x, $this->y]; + $this->fixedPosBlock = ''; + $this->fixedPosBlockDepth = 1; + } + /* -- END CSS-POSITION -- */ + if (preg_match('/\/$/', $e)) { + $this->tag->CloseTag($tag, $a, $i); + } + } + } // end TAG + } // end of foreach($a as $i=>$e) + + if ($close) { + // Close any open block tags + for ($b = $this->blklvl; $b > 0; $b--) { + $this->tag->CloseTag($this->blk[$b]['tag'], $a, $i); + } + + // Output any text left in buffer + if (count($this->textbuffer) && !$parseonly) { + $this->printbuffer($this->textbuffer); + } + if (!$parseonly) { + $this->textbuffer = []; + } + + /* -- CSS-FLOAT -- */ + // If ended with a float, need to move to end page + $currpos = $this->page * 1000 + $this->y; + if (isset($this->blk[$this->blklvl]['float_endpos']) && $this->blk[$this->blklvl]['float_endpos'] > $currpos) { + $old_page = $this->page; + $new_page = intval($this->blk[$this->blklvl]['float_endpos'] / 1000); + if ($old_page != $new_page) { + $s = $this->PrintPageBackgrounds(); + // Writes after the marker so not overwritten later by page background etc. + $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]); + $this->pageBackgrounds = []; + $this->page = $new_page; + $this->ResetMargins(); + $this->Reset(); + $this->pageoutput[$this->page] = []; + } + $this->y = (round($this->blk[$this->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; // mod changes operands to integers before processing + } + /* -- END CSS-FLOAT -- */ + + /* -- CSS-IMAGE-FLOAT -- */ + $this->printfloatbuffer(); + /* -- END CSS-IMAGE-FLOAT -- */ + + // Create Internal Links, if needed + if (!empty($this->internallink)) { + + foreach ($this->internallink as $k => $v) { + + if (strpos($k, "#") !== false) { + continue; + } + + if (!is_array($v)) { + continue; + } + + $ypos = $v['Y']; + $pagenum = $v['PAGE']; + $sharp = "#"; + + while (array_key_exists($sharp . $k, $this->internallink)) { + $internallink = $this->internallink[$sharp . $k]; + $this->SetLink($internallink, $ypos, $pagenum); + $sharp .= "#"; + } + } + } + + $this->bufferoutput = false; + + /* -- CSS-POSITION -- */ + if (count($this->fixedPosBlockSave)) { + foreach ($this->fixedPosBlockSave as $fpbs) { + $old_page = $this->page; + $this->page = $fpbs[2]; + $this->WriteFixedPosHTML($fpbs[0], 0, 0, 100, 100, 'auto', $fpbs[1]); // 0,0,10,10 are overwritten by bbox + $this->page = $old_page; + } + $this->fixedPosBlockSave = []; + } + /* -- END CSS-POSITION -- */ + } + } + + /* -- CSS-POSITION -- */ + + function WriteFixedPosHTML($html, $x, $y, $w, $h, $overflow = 'visible', $bounding = []) + { + // $overflow can be 'hidden', 'visible' or 'auto' - 'auto' causes autofit to size + // Annotations disabled - enabled in mPDF 5.0 + // Links do work + // Will always go on current page (or start Page 1 if required) + // Probably INCOMPATIBLE WITH keep with table, columns etc. + // Called externally or interally via
+ // When used internally, $x $y $w $h and $overflow are all overridden by $bounding + + $overflow = strtolower($overflow); + if ($this->state == 0) { + $this->AddPage($this->CurOrientation); + } + $save_y = $this->y; + $save_x = $this->x; + $this->fullImageHeight = $this->h; + $save_cols = false; + /* -- COLUMNS -- */ + if ($this->ColActive) { + $save_cols = true; + $save_nbcol = $this->NbCol; // other values of gap and vAlign will not change by setting Columns off + $this->SetColumns(0); + } + /* -- END COLUMNS -- */ + $save_annots = $this->title2annots; // *ANNOTATIONS* + $this->writingHTMLheader = true; // a FIX to stop pagebreaks etc. + $this->writingHTMLfooter = true; + $this->InFooter = true; // suppresses autopagebreaks + $save_bgs = $this->pageBackgrounds; + $checkinnerhtml = preg_replace('/\s/', '', $html); + $rotate = 0; + + if ($w > $this->w) { + $x = 0; + $w = $this->w; + } + if ($h > $this->h) { + $y = 0; + $h = $this->h; + } + if ($x > $this->w) { + $x = $this->w - $w; + } + if ($y > $this->h) { + $y = $this->h - $h; + } + + if (!empty($bounding)) { + // $cont_ containing block = full physical page (position: absolute) or page inside margins (position: fixed) + // $bbox_ Bounding box is the
which is positioned absolutely/fixed + // top/left/right/bottom/width/height/background*/border*/padding*/margin* are taken from bounding + // font*[family/size/style/weight]/line-height/text*[align/decoration/transform/indent]/color are transferred to $inner + // as an enclosing
(after having checked ID/CLASS) + // $x, $y, $w, $h are inside of $bbox_ = containing box for $inner_ + // $inner_ InnerHTML is the contents of that block to be output + $tag = $bounding[0]; + $attr = $bounding[1]; + $orig_x0 = $bounding[2]; + $orig_y0 = $bounding[3]; + + // As in WriteHTML() initialising + $this->blklvl = 0; + $this->lastblocklevelchange = 0; + $this->blk = []; + $this->initialiseBlock($this->blk[0]); + + $this->blk[0]['width'] = & $this->pgwidth; + $this->blk[0]['inner_width'] = & $this->pgwidth; + + $this->blk[0]['blockContext'] = $this->blockContext; + + $properties = $this->cssManager->MergeCSS('BLOCK', 'BODY', ''); + $this->setCSS($properties, '', 'BODY'); + $this->blklvl = 1; + $this->initialiseBlock($this->blk[1]); + $this->blk[1]['tag'] = $tag; + $this->blk[1]['attr'] = $attr; + $this->Reset(); + $p = $this->cssManager->MergeCSS('BLOCK', $tag, $attr); + if (isset($p['ROTATE']) && ($p['ROTATE'] == 90 || $p['ROTATE'] == -90 || $p['ROTATE'] == 180)) { + $rotate = $p['ROTATE']; + } // mPDF 6 + if (isset($p['OVERFLOW'])) { + $overflow = strtolower($p['OVERFLOW']); + } + if (strtolower($p['POSITION']) == 'fixed') { + $cont_w = $this->pgwidth; // $this->blk[0]['inner_width']; + $cont_h = $this->h - $this->tMargin - $this->bMargin; + $cont_x = $this->lMargin; + $cont_y = $this->tMargin; + } else { + $cont_w = $this->w; // ABSOLUTE; + $cont_h = $this->h; + $cont_x = 0; + $cont_y = 0; + } + + // Pass on in-line properties to the innerhtml + $css = ''; + if (isset($p['TEXT-ALIGN'])) { + $css .= 'text-align: ' . strtolower($p['TEXT-ALIGN']) . '; '; + } + if (isset($p['TEXT-TRANSFORM'])) { + $css .= 'text-transform: ' . strtolower($p['TEXT-TRANSFORM']) . '; '; + } + if (isset($p['TEXT-INDENT'])) { + $css .= 'text-indent: ' . strtolower($p['TEXT-INDENT']) . '; '; + } + if (isset($p['TEXT-DECORATION'])) { + $css .= 'text-decoration: ' . strtolower($p['TEXT-DECORATION']) . '; '; + } + if (isset($p['FONT-FAMILY'])) { + $css .= 'font-family: ' . strtolower($p['FONT-FAMILY']) . '; '; + } + if (isset($p['FONT-STYLE'])) { + $css .= 'font-style: ' . strtolower($p['FONT-STYLE']) . '; '; + } + if (isset($p['FONT-WEIGHT'])) { + $css .= 'font-weight: ' . strtolower($p['FONT-WEIGHT']) . '; '; + } + if (isset($p['FONT-SIZE'])) { + $css .= 'font-size: ' . strtolower($p['FONT-SIZE']) . '; '; + } + if (isset($p['LINE-HEIGHT'])) { + $css .= 'line-height: ' . strtolower($p['LINE-HEIGHT']) . '; '; + } + if (isset($p['TEXT-SHADOW'])) { + $css .= 'text-shadow: ' . strtolower($p['TEXT-SHADOW']) . '; '; + } + if (isset($p['LETTER-SPACING'])) { + $css .= 'letter-spacing: ' . strtolower($p['LETTER-SPACING']) . '; '; + } + // mPDF 6 + if (isset($p['FONT-VARIANT-POSITION'])) { + $css .= 'font-variant-position: ' . strtolower($p['FONT-VARIANT-POSITION']) . '; '; + } + if (isset($p['FONT-VARIANT-CAPS'])) { + $css .= 'font-variant-caps: ' . strtolower($p['FONT-VARIANT-CAPS']) . '; '; + } + if (isset($p['FONT-VARIANT-LIGATURES'])) { + $css .= 'font-variant-ligatures: ' . strtolower($p['FONT-VARIANT-LIGATURES']) . '; '; + } + if (isset($p['FONT-VARIANT-NUMERIC'])) { + $css .= 'font-variant-numeric: ' . strtolower($p['FONT-VARIANT-NUMERIC']) . '; '; + } + if (isset($p['FONT-VARIANT-ALTERNATES'])) { + $css .= 'font-variant-alternates: ' . strtolower($p['FONT-VARIANT-ALTERNATES']) . '; '; + } + if (isset($p['FONT-FEATURE-SETTINGS'])) { + $css .= 'font-feature-settings: ' . strtolower($p['FONT-FEATURE-SETTINGS']) . '; '; + } + if (isset($p['FONT-LANGUAGE-OVERRIDE'])) { + $css .= 'font-language-override: ' . strtolower($p['FONT-LANGUAGE-OVERRIDE']) . '; '; + } + if (isset($p['FONT-KERNING'])) { + $css .= 'font-kerning: ' . strtolower($p['FONT-KERNING']) . '; '; + } + + if (isset($p['COLOR'])) { + $css .= 'color: ' . strtolower($p['COLOR']) . '; '; + } + if (isset($p['Z-INDEX'])) { + $css .= 'z-index: ' . $p['Z-INDEX'] . '; '; + } + if ($css) { + $html = '
' . $html . '
'; + } + // Copy over (only) the properties to set for border and background + $pb = []; + $pb['MARGIN-TOP'] = (isset($p['MARGIN-TOP']) ? $p['MARGIN-TOP'] : ''); + $pb['MARGIN-RIGHT'] = (isset($p['MARGIN-RIGHT']) ? $p['MARGIN-RIGHT'] : ''); + $pb['MARGIN-BOTTOM'] = (isset($p['MARGIN-BOTTOM']) ? $p['MARGIN-BOTTOM'] : ''); + $pb['MARGIN-LEFT'] = (isset($p['MARGIN-LEFT']) ? $p['MARGIN-LEFT'] : ''); + $pb['PADDING-TOP'] = (isset($p['PADDING-TOP']) ? $p['PADDING-TOP'] : ''); + $pb['PADDING-RIGHT'] = (isset($p['PADDING-RIGHT']) ? $p['PADDING-RIGHT'] : ''); + $pb['PADDING-BOTTOM'] = (isset($p['PADDING-BOTTOM']) ? $p['PADDING-BOTTOM'] : ''); + $pb['PADDING-LEFT'] = (isset($p['PADDING-LEFT']) ? $p['PADDING-LEFT'] : ''); + $pb['BORDER-TOP'] = (isset($p['BORDER-TOP']) ? $p['BORDER-TOP'] : ''); + $pb['BORDER-RIGHT'] = (isset($p['BORDER-RIGHT']) ? $p['BORDER-RIGHT'] : ''); + $pb['BORDER-BOTTOM'] = (isset($p['BORDER-BOTTOM']) ? $p['BORDER-BOTTOM'] : ''); + $pb['BORDER-LEFT'] = (isset($p['BORDER-LEFT']) ? $p['BORDER-LEFT'] : ''); + if (isset($p['BORDER-TOP-LEFT-RADIUS-H'])) { + $pb['BORDER-TOP-LEFT-RADIUS-H'] = $p['BORDER-TOP-LEFT-RADIUS-H']; + } + if (isset($p['BORDER-TOP-LEFT-RADIUS-V'])) { + $pb['BORDER-TOP-LEFT-RADIUS-V'] = $p['BORDER-TOP-LEFT-RADIUS-V']; + } + if (isset($p['BORDER-TOP-RIGHT-RADIUS-H'])) { + $pb['BORDER-TOP-RIGHT-RADIUS-H'] = $p['BORDER-TOP-RIGHT-RADIUS-H']; + } + if (isset($p['BORDER-TOP-RIGHT-RADIUS-V'])) { + $pb['BORDER-TOP-RIGHT-RADIUS-V'] = $p['BORDER-TOP-RIGHT-RADIUS-V']; + } + if (isset($p['BORDER-BOTTOM-LEFT-RADIUS-H'])) { + $pb['BORDER-BOTTOM-LEFT-RADIUS-H'] = $p['BORDER-BOTTOM-LEFT-RADIUS-H']; + } + if (isset($p['BORDER-BOTTOM-LEFT-RADIUS-V'])) { + $pb['BORDER-BOTTOM-LEFT-RADIUS-V'] = $p['BORDER-BOTTOM-LEFT-RADIUS-V']; + } + if (isset($p['BORDER-BOTTOM-RIGHT-RADIUS-H'])) { + $pb['BORDER-BOTTOM-RIGHT-RADIUS-H'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-H']; + } + if (isset($p['BORDER-BOTTOM-RIGHT-RADIUS-V'])) { + $pb['BORDER-BOTTOM-RIGHT-RADIUS-V'] = $p['BORDER-BOTTOM-RIGHT-RADIUS-V']; + } + if (isset($p['BACKGROUND-COLOR'])) { + $pb['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; + } + if (isset($p['BOX-SHADOW'])) { + $pb['BOX-SHADOW'] = $p['BOX-SHADOW']; + } + /* -- BACKGROUNDS -- */ + if (isset($p['BACKGROUND-IMAGE'])) { + $pb['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; + } + if (isset($p['BACKGROUND-IMAGE-RESIZE'])) { + $pb['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; + } + if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { + $pb['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; + } + if (isset($p['BACKGROUND-REPEAT'])) { + $pb['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; + } + if (isset($p['BACKGROUND-POSITION'])) { + $pb['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; + } + if (isset($p['BACKGROUND-GRADIENT'])) { + $pb['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; + } + if (isset($p['BACKGROUND-SIZE'])) { + $pb['BACKGROUND-SIZE'] = $p['BACKGROUND-SIZE']; + } + if (isset($p['BACKGROUND-ORIGIN'])) { + $pb['BACKGROUND-ORIGIN'] = $p['BACKGROUND-ORIGIN']; + } + if (isset($p['BACKGROUND-CLIP'])) { + $pb['BACKGROUND-CLIP'] = $p['BACKGROUND-CLIP']; + } + + /* -- END BACKGROUNDS -- */ + + $this->setCSS($pb, 'BLOCK', $tag); + + // ================================================================ + $bbox_br = $this->blk[1]['border_right']['w']; + $bbox_bl = $this->blk[1]['border_left']['w']; + $bbox_bt = $this->blk[1]['border_top']['w']; + $bbox_bb = $this->blk[1]['border_bottom']['w']; + $bbox_pr = $this->blk[1]['padding_right']; + $bbox_pl = $this->blk[1]['padding_left']; + $bbox_pt = $this->blk[1]['padding_top']; + $bbox_pb = $this->blk[1]['padding_bottom']; + $bbox_mr = $this->blk[1]['margin_right']; + if (isset($p['MARGIN-RIGHT']) && strtolower($p['MARGIN-RIGHT']) == 'auto') { + $bbox_mr = 'auto'; + } + $bbox_ml = $this->blk[1]['margin_left']; + if (isset($p['MARGIN-LEFT']) && strtolower($p['MARGIN-LEFT']) == 'auto') { + $bbox_ml = 'auto'; + } + $bbox_mt = $this->blk[1]['margin_top']; + if (isset($p['MARGIN-TOP']) && strtolower($p['MARGIN-TOP']) == 'auto') { + $bbox_mt = 'auto'; + } + $bbox_mb = $this->blk[1]['margin_bottom']; + if (isset($p['MARGIN-BOTTOM']) && strtolower($p['MARGIN-BOTTOM']) == 'auto') { + $bbox_mb = 'auto'; + } + if (isset($p['LEFT']) && strtolower($p['LEFT']) != 'auto') { + $bbox_left = $this->sizeConverter->convert($p['LEFT'], $cont_w, $this->FontSize, false); + } else { + $bbox_left = 'auto'; + } + if (isset($p['TOP']) && strtolower($p['TOP']) != 'auto') { + $bbox_top = $this->sizeConverter->convert($p['TOP'], $cont_h, $this->FontSize, false); + } else { + $bbox_top = 'auto'; + } + if (isset($p['RIGHT']) && strtolower($p['RIGHT']) != 'auto') { + $bbox_right = $this->sizeConverter->convert($p['RIGHT'], $cont_w, $this->FontSize, false); + } else { + $bbox_right = 'auto'; + } + if (isset($p['BOTTOM']) && strtolower($p['BOTTOM']) != 'auto') { + $bbox_bottom = $this->sizeConverter->convert($p['BOTTOM'], $cont_h, $this->FontSize, false); + } else { + $bbox_bottom = 'auto'; + } + if (isset($p['WIDTH']) && strtolower($p['WIDTH']) != 'auto') { + $inner_w = $this->sizeConverter->convert($p['WIDTH'], $cont_w, $this->FontSize, false); + } else { + $inner_w = 'auto'; + } + if (isset($p['HEIGHT']) && strtolower($p['HEIGHT']) != 'auto') { + $inner_h = $this->sizeConverter->convert($p['HEIGHT'], $cont_h, $this->FontSize, false); + } else { + $inner_h = 'auto'; + } + + // If bottom or right pos are set and not left / top - save this to adjust rotated block later + if ($rotate == 90 || $rotate == -90) { // mPDF 6 + if ($bbox_left === 'auto' && $bbox_right !== 'auto') { + $rot_rpos = $bbox_right; + } else { + $rot_rpos = false; + } + if ($bbox_top === 'auto' && $bbox_bottom !== 'auto') { + $rot_bpos = $bbox_bottom; + } else { + $rot_bpos = false; + } + } + + // ================================================================ + if ($checkinnerhtml == '' && $inner_h === 'auto') { + $inner_h = 0.0001; + } + if ($checkinnerhtml == '' && $inner_w === 'auto') { + $inner_w = 2 * $this->GetCharWidth('W', false); + } + // ================================================================ + // Algorithm from CSS2.1 See http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height + // mPD 5.3.14 + // Special case (not CSS) if all not specified, centre vertically on page + $bbox_top_orig = ''; + if ($bbox_top === 'auto' && $inner_h === 'auto' && $bbox_bottom === 'auto' && $bbox_mt === 'auto' && $bbox_mb === 'auto') { + $bbox_top_orig = $bbox_top; + if ($bbox_mt === 'auto') { + $bbox_mt = 0; + } + if ($bbox_mb === 'auto') { + $bbox_mb = 0; + } + $bbox_top = $orig_y0 - $bbox_mt - $cont_y; + // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto' + } // mPD 5.3.14 + elseif ($bbox_top === 'auto' && $inner_h === 'auto' && $bbox_bottom === 'auto') { + $bbox_top_orig = $bbox_top = $orig_y0 - $cont_y; + if ($bbox_mt === 'auto') { + $bbox_mt = 0; + } + if ($bbox_mb === 'auto') { + $bbox_mb = 0; + } + // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto' + } elseif ($bbox_top !== 'auto' && $inner_h !== 'auto' && $bbox_bottom !== 'auto') { + if ($bbox_mt === 'auto' && $bbox_mb === 'auto') { + $x = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom; + $bbox_mt = $bbox_mb = ($x / 2); + } elseif ($bbox_mt === 'auto') { + $bbox_mt = $cont_h - $bbox_top - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom; + } elseif ($bbox_mb === 'auto') { + $bbox_mb = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_bottom; + } else { + $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt; + } + } else { + if ($bbox_mt === 'auto') { + $bbox_mt = 0; + } + if ($bbox_mb === 'auto') { + $bbox_mb = 0; + } + if ($bbox_top === 'auto' && $inner_h === 'auto' && $bbox_bottom !== 'auto') { + // solve for $bbox_top when content_h known - $inner_h=='auto' && $bbox_top =='auto' + } elseif ($bbox_top === 'auto' && $bbox_bottom === 'auto' && $inner_h !== 'auto') { + $bbox_top = $orig_y0 - $bbox_mt - $cont_y; + $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt; + } elseif ($inner_h === 'auto' && $bbox_bottom === 'auto' && $bbox_top !== 'auto') { + // solve for $bbox_bottom when content_h known - $inner_h=='auto' && $bbox_bottom=='auto' + } elseif ($bbox_top === 'auto' && $inner_h !== 'auto' && $bbox_bottom !== 'auto') { + $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom; + } elseif ($inner_h === 'auto' && $bbox_top !== 'auto' && $bbox_bottom !== 'auto') { + $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mt - $bbox_bottom; + } elseif ($bbox_bottom === 'auto' && $bbox_top !== 'auto' && $inner_h !== 'auto') { + $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mt; + } + } + + // THEN DO SAME FOR WIDTH + // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width + if ($bbox_left === 'auto' && $inner_w === 'auto' && $bbox_right === 'auto') { + if ($bbox_ml === 'auto') { + $bbox_ml = 0; + } + if ($bbox_mr === 'auto') { + $bbox_mr = 0; + } + // IF containing element RTL, should set $bbox_right + $bbox_left = $orig_x0 - $bbox_ml - $cont_x; + // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto' + } elseif ($bbox_left !== 'auto' && $inner_w !== 'auto' && $bbox_right !== 'auto') { + if ($bbox_ml === 'auto' && $bbox_mr === 'auto') { + $x = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right; + $bbox_ml = $bbox_mr = ($x / 2); + } elseif ($bbox_ml === 'auto') { + $bbox_ml = $cont_w - $bbox_left - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right; + } elseif ($bbox_mr === 'auto') { + $bbox_mr = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_right; + } else { + $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml; + } + } else { + if ($bbox_ml === 'auto') { + $bbox_ml = 0; + } + if ($bbox_mr === 'auto') { + $bbox_mr = 0; + } + if ($bbox_left === 'auto' && $inner_w === 'auto' && $bbox_right !== 'auto') { + // solve for $bbox_left when content_w known - $inner_w=='auto' && $bbox_left =='auto' + } elseif ($bbox_left === 'auto' && $bbox_right === 'auto' && $inner_w !== 'auto') { + // IF containing element RTL, should set $bbox_right + $bbox_left = $orig_x0 - $bbox_ml - $cont_x; + $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml; + } elseif ($inner_w === 'auto' && $bbox_right === 'auto' && $bbox_left !== 'auto') { + // solve for $bbox_right when content_w known - $inner_w=='auto' && $bbox_right=='auto' + } elseif ($bbox_left === 'auto' && $inner_w !== 'auto' && $bbox_right !== 'auto') { + $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right; + } elseif ($inner_w === 'auto' && $bbox_left !== 'auto' && $bbox_right !== 'auto') { + $inner_w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right; + } elseif ($bbox_right === 'auto' && $bbox_left !== 'auto' && $inner_w !== 'auto') { + $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml; + } + } + + // ================================================================ + // ================================================================ + /* -- BACKGROUNDS -- */ + if (isset($pb['BACKGROUND-IMAGE']) && $pb['BACKGROUND-IMAGE']) { + $ret = $this->SetBackground($pb, $this->blk[1]['inner_width']); + if ($ret) { + $this->blk[1]['background-image'] = $ret; + } + } + /* -- END BACKGROUNDS -- */ + + $bbox_top_auto = $bbox_top === 'auto'; + $bbox_left_auto = $bbox_left === 'auto'; + $bbox_right_auto = $bbox_right === 'auto'; + $bbox_bottom_auto = $bbox_bottom === 'auto'; + + $bbox_top = is_numeric($bbox_top) ? $bbox_top : 0; + $bbox_left = is_numeric($bbox_left) ? $bbox_left : 0; + $bbox_right = is_numeric($bbox_right) ? $bbox_right : 0; + $bbox_bottom = is_numeric($bbox_bottom) ? $bbox_bottom : 0; + + $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt; + $h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom; + + $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl; + $w = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $bbox_pr - $bbox_br - $bbox_mr - $bbox_right; + + // Set (temporary) values for x y w h to do first paint, if values are auto + if ($inner_h === 'auto' && $bbox_top_auto) { + $y = $cont_y + $bbox_mt + $bbox_bt + $bbox_pt; + $h = $cont_h - ($bbox_bottom + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb); + } elseif ($inner_h === 'auto' && $bbox_bottom_auto) { + $y = $cont_y + $bbox_top + $bbox_mt + $bbox_bt + $bbox_pt; + $h = $cont_h - ($bbox_top + $bbox_mt + $bbox_mb + $bbox_bt + $bbox_bb + $bbox_pt + $bbox_pb); + } + if ($inner_w === 'auto' && $bbox_left_auto) { + $x = $cont_x + $bbox_ml + $bbox_bl + $bbox_pl; + $w = $cont_w - ($bbox_right + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr); + } elseif ($inner_w === 'auto' && $bbox_right_auto) { + $x = $cont_x + $bbox_left + $bbox_ml + $bbox_bl + $bbox_pl; + $w = $cont_w - ($bbox_left + $bbox_ml + $bbox_mr + $bbox_bl + $bbox_br + $bbox_pl + $bbox_pr); + } + + $bbox_y = $cont_y + $bbox_top + $bbox_mt; + $bbox_x = $cont_x + $bbox_left + $bbox_ml; + + $saved_block1 = $this->blk[1]; + + unset($p); + unset($pb); + + // ================================================================ + if ($inner_w === 'auto') { // do a first write + $this->lMargin = $x; + $this->rMargin = $this->w - $w - $x; + + // SET POSITION & FONT VALUES + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->pageoutput[$this->page] = []; + $this->x = $x; + $this->y = $y; + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + $this->pageBackgrounds = []; + $this->maxPosR = 0; + $this->maxPosL = $this->w; // For RTL + $this->WriteHTML($html, HTMLParserMode::HTML_HEADER_BUFFER); + $inner_w = $this->maxPosR - $this->lMargin; + if ($bbox_right_auto) { + $bbox_right = $cont_w - $bbox_left - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml; + } elseif ($bbox_left_auto) { + $bbox_left = $cont_w - $bbox_ml - $bbox_bl - $bbox_pl - $inner_w - $bbox_pr - $bbox_br - $bbox_ml - $bbox_right; + $bbox_x = $cont_x + $bbox_left + $bbox_ml; + $inner_x = $bbox_x + $bbox_bl + $bbox_pl; + $x = $inner_x; + } + + $w = $inner_w; + $bbox_y = $cont_y + $bbox_top + $bbox_mt; + $bbox_x = $cont_x + $bbox_left + $bbox_ml; + } + + if ($inner_h === 'auto') { // do a first write + + $this->lMargin = $x; + $this->rMargin = $this->w - $w - $x; + + // SET POSITION & FONT VALUES + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->pageoutput[$this->page] = []; + $this->x = $x; + $this->y = $y; + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + $this->pageBackgrounds = []; + $this->WriteHTML($html, HTMLParserMode::HTML_HEADER_BUFFER); + $inner_h = $this->y - $y; + + if ($overflow != 'hidden' && $overflow != 'visible') { // constrained + if (($this->y + $bbox_pb + $bbox_bb) > ($cont_y + $cont_h)) { + $adj = ($this->y + $bbox_pb + $bbox_bb) - ($cont_y + $cont_h); + $inner_h -= $adj; + } + } + if ($bbox_bottom_auto && $bbox_top_orig === 'auto') { + $bbox_bottom = $bbox_top = ($cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb) / 2; + if ($overflow != 'hidden' && $overflow != 'visible') { // constrained + if ($bbox_top < 0) { + $bbox_top = 0; + $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom; + } + } + $bbox_y = $cont_y + $bbox_top + $bbox_mt; + $inner_y = $bbox_y + $bbox_bt + $bbox_pt; + $y = $inner_y; + } elseif ($bbox_bottom_auto) { + $bbox_bottom = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb; + } elseif ($bbox_top_auto) { + $bbox_top = $cont_h - $bbox_mt - $bbox_bt - $bbox_pt - $inner_h - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom; + if ($overflow != 'hidden' && $overflow != 'visible') { // constrained + if ($bbox_top < 0) { + $bbox_top = 0; + $inner_h = $cont_h - $bbox_top - $bbox_mt - $bbox_bt - $bbox_pt - $bbox_pb - $bbox_bb - $bbox_mb - $bbox_bottom; + } + } + $bbox_y = $cont_y + $bbox_top + $bbox_mt; + $inner_y = $bbox_y + $bbox_bt + $bbox_pt; + $y = $inner_y; + } + $h = $inner_h; + $bbox_y = $cont_y + $bbox_top + $bbox_mt; + $bbox_x = $cont_x + $bbox_left + $bbox_ml; + } + + $inner_w = $w; + $inner_h = $h; + } + + $this->lMargin = $x; + $this->rMargin = $this->w - $w - $x; + + // SET POSITION & FONT VALUES + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->pageoutput[$this->page] = []; + + $this->x = $x; + $this->y = $y; + + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + + $this->pageBackgrounds = []; + + $this->WriteHTML($html, HTMLParserMode::HTML_HEADER_BUFFER); + + $actual_h = $this->y - $y; + $use_w = $w; + $use_h = $h; + $ratio = $actual_h / $use_w; + + if ($overflow != 'hidden' && $overflow != 'visible') { + $target = $h / $w; + if ($target > 0) { + if (($ratio / $target) > 1) { + $nl = ceil($actual_h / $this->lineheight); + $l = $use_w * $nl; + $est_w = sqrt(($l * $this->lineheight) / $target) * 0.8; + $use_w += ($est_w - $use_w) - ($w / 100); + } + $bpcstart = ($ratio / $target); + $bpcctr = 1; + + while (($ratio / $target) > 1) { + // @log 'Auto-sizing fixed-position block $bpcctr++ + + $this->x = $x; + $this->y = $y; + + if (($ratio / $target) > 1.5 || ($ratio / $target) < 0.6) { + $use_w += ($w / $this->incrementFPR1); + } elseif (($ratio / $target) > 1.2 || ($ratio / $target) < 0.85) { + $use_w += ($w / $this->incrementFPR2); + } elseif (($ratio / $target) > 1.1 || ($ratio / $target) < 0.91) { + $use_w += ($w / $this->incrementFPR3); + } else { + $use_w += ($w / $this->incrementFPR4); + } + + $use_h = $use_w * $target; + $this->rMargin = $this->w - $use_w - $x; + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + $this->pageBackgrounds = []; + $this->WriteHTML($html, HTMLParserMode::HTML_HEADER_BUFFER); + $actual_h = $this->y - $y; + $ratio = $actual_h / $use_w; + } + } + } + + $shrink_f = $w / $use_w; + + // ================================================================ + + $this->pages[$this->page] .= '___BEFORE_BORDERS___'; + $block_s = $this->PrintPageBackgrounds(); // Save to print later inside clipping path + $this->pageBackgrounds = []; + + // ================================================================ + + if ($rotate == 90 || $rotate == -90) { // mPDF 6 + $prerotw = $bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br; + $preroth = $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb; + $rot_start = " q\n"; + if ($rotate == 90) { + if ($rot_rpos !== false) { + $adjw = $prerotw; + } // width before rotation + else { + $adjw = $preroth; + } // height before rotation + if ($rot_bpos !== false) { + $adjh = -$prerotw + $preroth; + } else { + $adjh = 0; + } + } else { + if ($rot_rpos !== false) { + $adjw = $prerotw - $preroth; + } else { + $adjw = 0; + } + if ($rot_bpos !== false) { + $adjh = $preroth; + } // height before rotation + else { + $adjh = $prerotw; + } // width before rotation + } + $rot_start .= $this->transformTranslate($adjw, $adjh, true) . "\n"; + $rot_start .= $this->transformRotate($rotate, $bbox_x, $bbox_y, true) . "\n"; + $rot_end = " Q\n"; + } elseif ($rotate == 180) { // mPDF 6 + $rot_start = " q\n"; + $rot_start .= $this->transformTranslate($bbox_bl + $bbox_pl + $inner_w + $bbox_pr + $bbox_br, $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb, true) . "\n"; + $rot_start .= $this->transformRotate(180, $bbox_x, $bbox_y, true) . "\n"; + $rot_end = " Q\n"; + } else { + $rot_start = ''; + $rot_end = ''; + } + + // ================================================================ + if (!empty($bounding)) { + // WHEN HEIGHT // BOTTOM EDGE IS KNOWN and $this->y is set to the bottom + // Re-instate saved $this->blk[1] + $this->blk[1] = $saved_block1; + + // These are only needed when painting border/background + $this->blk[1]['width'] = $bbox_w = $cont_w - $bbox_left - $bbox_ml - $bbox_mr - $bbox_right; + $this->blk[1]['x0'] = $bbox_x; + $this->blk[1]['y0'] = $bbox_y; + $this->blk[1]['startpage'] = $this->page; + $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb; + $this->writer->write($rot_start); + $this->PaintDivBB('', 0, 1); // Prints borders and sets backgrounds in $this->pageBackgrounds + $this->writer->write($rot_end); + } + + $s = $this->PrintPageBackgrounds(); + $s = $rot_start . $s . $rot_end; + $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n" . $s . "\n", $this->pages[$this->page]); + $this->pageBackgrounds = []; + + $this->writer->write($rot_start); + + // Clipping Output + if ($overflow == 'hidden') { + // Bounding rectangle to clip + $clip_y1 = $this->y; + if (!empty($bounding) && ($this->y + $bbox_pb + $bbox_bb) > ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb )) { + $clip_y1 = ($bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb ) - ($bbox_pb + $bbox_bb); + } + // $op = 'W* n'; // Clipping + $op = 'W n'; // Clipping alternative mode + $this->writer->write("q"); + $ch = $clip_y1 - $y; + $this->writer->write(sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op)); + if (!empty($block_s)) { + $tmp = "q\n" . sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op); + $tmp .= "\n" . $block_s . "\nQ"; + $block_s = $tmp; + } + } + + + if (!empty($block_s)) { + if ($shrink_f != 1) { // i.e. autofit has resized the box + $tmp = "q\n" . $this->transformScale(($shrink_f * 100), ($shrink_f * 100), $x, $y, true); + $tmp .= "\n" . $block_s . "\nQ"; + $block_s = $tmp; + } + $this->writer->write($block_s); + } + + + + if ($shrink_f != 1) { // i.e. autofit has resized the box + $this->StartTransform(); + $this->transformScale(($shrink_f * 100), ($shrink_f * 100), $x, $y); + } + + $this->writer->write($this->headerbuffer); + + if ($shrink_f != 1) { // i.e. autofit has resized the box + $this->StopTransform(); + } + + if ($overflow == 'hidden') { + // End clipping + $this->writer->write("Q"); + } + + $this->writer->write($rot_end); + + + // Page Links + foreach ($this->HTMLheaderPageLinks as $lk) { + if ($rotate) { + $tmp = $lk[2]; // Switch h - w + $lk[2] = $lk[3]; + $lk[3] = $tmp; + + $lx1 = (($lk[0] / Mpdf::SCALE)); + $ly1 = (($this->h - ($lk[1] / Mpdf::SCALE))); + if ($rotate == 90) { + $adjx = -($lx1 - $bbox_x) + ($preroth - ($ly1 - $bbox_y)); + $adjy = -($ly1 - $bbox_y) + ($lx1 - $bbox_x); + $lk[2] = -$lk[2]; + } elseif ($rotate == -90) { + $adjx = -($lx1 - $bbox_x) + ($ly1 - $bbox_y); + $adjy = -($ly1 - $bbox_y) - ($lx1 - $bbox_x) + $prerotw; + $lk[3] = -$lk[3]; + } + if ($rot_rpos !== false) { + $adjx += $prerotw - $preroth; + } + if ($rot_bpos !== false) { + $adjy += $preroth - $prerotw; + } + $lx1 += $adjx; + $ly1 += $adjy; + + $lk[0] = $lx1 * Mpdf::SCALE; + $lk[1] = ($this->h - $ly1) * Mpdf::SCALE; + } + if ($shrink_f != 1) { // i.e. autofit has resized the box + $lx1 = (($lk[0] / Mpdf::SCALE) - $x); + $lx2 = $x + ($lx1 * $shrink_f); + $lk[0] = $lx2 * Mpdf::SCALE; + $ly1 = (($this->h - ($lk[1] / Mpdf::SCALE)) - $y); + $ly2 = $y + ($ly1 * $shrink_f); + $lk[1] = ($this->h - $ly2) * Mpdf::SCALE; + $lk[2] *= $shrink_f; // width + $lk[3] *= $shrink_f; // height + } + $this->PageLinks[$this->page][] = $lk; + } + + foreach ($this->HTMLheaderPageForms as $n => $f) { + if ($shrink_f != 1) { // i.e. autofit has resized the box + $f['x'] = $x + (($f['x'] - $x) * $shrink_f); + $f['y'] = $y + (($f['y'] - $y) * $shrink_f); + $f['w'] *= $shrink_f; + $f['h'] *= $shrink_f; + $f['style']['fontsize'] *= $shrink_f; + } + $this->form->forms[$f['n']] = $f; + } + // Page Annotations + foreach ($this->HTMLheaderPageAnnots as $lk) { + if ($rotate) { + if ($rotate == 90) { + $adjx = -($lk['x'] - $bbox_x) + ($preroth - ($lk['y'] - $bbox_y)); + $adjy = -($lk['y'] - $bbox_y) + ($lk['x'] - $bbox_x); + } elseif ($rotate == -90) { + $adjx = -($lk['x'] - $bbox_x) + ($lk['y'] - $bbox_y); + $adjy = -($lk['y'] - $bbox_y) - ($lk['x'] - $bbox_x) + $prerotw; + } + if ($rot_rpos !== false) { + $adjx += $prerotw - $preroth; + } + if ($rot_bpos !== false) { + $adjy += $preroth - $prerotw; + } + $lk['x'] += $adjx; + $lk['y'] += $adjy; + } + if ($shrink_f != 1) { // i.e. autofit has resized the box + $lk['x'] = $x + (($lk['x'] - $x) * $shrink_f); + $lk['y'] = $y + (($lk['y'] - $y) * $shrink_f); + } + $this->PageAnnots[$this->page][] = $lk; + } + + // Restore + $this->headerbuffer = ''; + $this->HTMLheaderPageLinks = []; + $this->HTMLheaderPageAnnots = []; + $this->HTMLheaderPageForms = []; + $this->pageBackgrounds = $save_bgs; + $this->writingHTMLheader = false; + + $this->writingHTMLfooter = false; + $this->fullImageHeight = false; + $this->ResetMargins(); + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->SetXY($save_x, $save_y); + $this->title2annots = $save_annots; // *ANNOTATIONS* + $this->InFooter = false; // turns back on autopagebreaks + $this->pageoutput[$this->page] = []; + $this->pageoutput[$this->page]['Font'] = ''; + /* -- COLUMNS -- */ + if ($save_cols) { + $this->SetColumns($save_nbcol, $this->colvAlign, $this->ColGap); + } + /* -- END COLUMNS -- */ + } + + /* -- END CSS-POSITION -- */ + + function initialiseBlock(&$blk) + { + $blk['margin_top'] = 0; + $blk['margin_left'] = 0; + $blk['margin_bottom'] = 0; + $blk['margin_right'] = 0; + $blk['padding_top'] = 0; + $blk['padding_left'] = 0; + $blk['padding_bottom'] = 0; + $blk['padding_right'] = 0; + $blk['border_top']['w'] = 0; + $blk['border_left']['w'] = 0; + $blk['border_bottom']['w'] = 0; + $blk['border_right']['w'] = 0; + $blk['direction'] = 'ltr'; + $blk['hide'] = false; + $blk['outer_left_margin'] = 0; + $blk['outer_right_margin'] = 0; + $blk['cascadeCSS'] = []; + $blk['block-align'] = false; + $blk['bgcolor'] = false; + $blk['page_break_after_avoid'] = false; + $blk['keep_block_together'] = false; + $blk['float'] = false; + $blk['line_height'] = ''; + $blk['margin_collapse'] = false; + } + + function border_details($bd) + { + $prop = preg_split('/\s+/', trim($bd)); + + if (isset($this->blk[$this->blklvl]['inner_width'])) { + $refw = $this->blk[$this->blklvl]['inner_width']; + } elseif (isset($this->blk[$this->blklvl - 1]['inner_width'])) { + $refw = $this->blk[$this->blklvl - 1]['inner_width']; + } else { + $refw = $this->w; + } + if (count($prop) == 1) { + $bsize = $this->sizeConverter->convert($prop[0], $refw, $this->FontSize, false); + if ($bsize > 0) { + return ['s' => 1, 'w' => $bsize, 'c' => $this->colorConverter->convert(0, $this->PDFAXwarnings), 'style' => 'solid']; + } else { + return ['w' => 0, 's' => 0]; + } + } elseif (count($prop) == 2) { + // 1px solid + if (in_array($prop[1], $this->borderstyles) || $prop[1] == 'none' || $prop[1] == 'hidden') { + $prop[2] = ''; + } // solid #000000 + elseif (in_array($prop[0], $this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden') { + $prop[0] = ''; + $prop[1] = $prop[0]; + $prop[2] = $prop[1]; + } // 1px #000000 + else { + $prop[1] = ''; + $prop[2] = $prop[1]; + } + } elseif (count($prop) == 3) { + // Change #000000 1px solid to 1px solid #000000 (proper) + if (substr($prop[0], 0, 1) == '#') { + $tmp = $prop[0]; + $prop[0] = $prop[1]; + $prop[1] = $prop[2]; + $prop[2] = $tmp; + } // Change solid #000000 1px to 1px solid #000000 (proper) + elseif (substr($prop[0], 1, 1) == '#') { + $tmp = $prop[1]; + $prop[0] = $prop[2]; + $prop[1] = $prop[0]; + $prop[2] = $tmp; + } // Change solid 1px #000000 to 1px solid #000000 (proper) + elseif (in_array($prop[0], $this->borderstyles) || $prop[0] == 'none' || $prop[0] == 'hidden') { + $tmp = $prop[0]; + $prop[0] = $prop[1]; + $prop[1] = $tmp; + } + } else { + return ['w' => 0, 's' => 0]; + } + // Size + $bsize = $this->sizeConverter->convert($prop[0], $refw, $this->FontSize, false); + // color + $coul = $this->colorConverter->convert($prop[2], $this->PDFAXwarnings); // returns array + // Style + $prop[1] = strtolower($prop[1]); + if (in_array($prop[1], $this->borderstyles) && $bsize > 0) { + $on = 1; + } elseif ($prop[1] == 'hidden') { + $on = 1; + $bsize = 0; + $coul = ''; + } elseif ($prop[1] == 'none') { + $on = 0; + $bsize = 0; + $coul = ''; + } else { + $on = 0; + $bsize = 0; + $coul = ''; + $prop[1] = ''; + } + return ['s' => $on, 'w' => $bsize, 'c' => $coul, 'style' => $prop[1], 'dom' => 0]; + } + + /* -- END HTML-CSS -- */ + + + /* -- BORDER-RADIUS -- */ + + function _borderPadding($a, $b, &$px, &$py) + { + // $px and py are padding long axis (x) and short axis (y) + $added = 0; // extra padding + + $x = $a - $px; + $y = $b - $py; + // Check if Falls within ellipse of border radius + if (( (($x + $added) * ($x + $added)) / ($a * $a) + (($y + $added) * ($y + $added)) / ($b * $b) ) <= 1) { + return false; + } + + $t = atan2($y, $x); + + $newx = $b / sqrt((($b * $b) / ($a * $a)) + ( tan($t) * tan($t) )); + $newy = $a / sqrt((($a * $a) / ($b * $b)) + ( (1 / tan($t)) * (1 / tan($t)) )); + $px = max($px, $a - $newx + $added); + $py = max($py, $b - $newy + $added); + } + + /* -- END BORDER-RADIUS -- */ + /* -- HTML-CSS -- */ + /* -- CSS-PAGE -- */ + + function SetPagedMediaCSS($name, $first, $oddEven) + { + if ($oddEven == 'E') { + if ($this->directionality == 'rtl') { + $side = 'R'; + } else { + $side = 'L'; + } + } else { + if ($this->directionality == 'rtl') { + $side = 'L'; + } else { + $side = 'R'; + } + } + $name = strtoupper($name); + $p = []; + $p['SIZE'] = 'AUTO'; + + // Uses mPDF original margins as default + $p['MARGIN-RIGHT'] = strval($this->orig_rMargin) . 'mm'; + $p['MARGIN-LEFT'] = strval($this->orig_lMargin) . 'mm'; + $p['MARGIN-TOP'] = strval($this->orig_tMargin) . 'mm'; + $p['MARGIN-BOTTOM'] = strval($this->orig_bMargin) . 'mm'; + $p['MARGIN-HEADER'] = strval($this->orig_hMargin) . 'mm'; + $p['MARGIN-FOOTER'] = strval($this->orig_fMargin) . 'mm'; + + // Basic page + selector + if (isset($this->cssManager->CSS['@PAGE'])) { + $zp = $this->cssManager->CSS['@PAGE']; + } else { + $zp = []; + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + if (isset($p['EVEN-HEADER-NAME']) && $oddEven == 'E') { + $p['HEADER'] = $p['EVEN-HEADER-NAME']; + unset($p['EVEN-HEADER-NAME']); + } + if (isset($p['ODD-HEADER-NAME']) && $oddEven != 'E') { + $p['HEADER'] = $p['ODD-HEADER-NAME']; + unset($p['ODD-HEADER-NAME']); + } + if (isset($p['EVEN-FOOTER-NAME']) && $oddEven == 'E') { + $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; + unset($p['EVEN-FOOTER-NAME']); + } + if (isset($p['ODD-FOOTER-NAME']) && $oddEven != 'E') { + $p['FOOTER'] = $p['ODD-FOOTER-NAME']; + unset($p['ODD-FOOTER-NAME']); + } + + // If right/Odd page + if (isset($this->cssManager->CSS['@PAGE>>PSEUDO>>RIGHT']) && $side == 'R') { + $zp = $this->cssManager->CSS['@PAGE>>PSEUDO>>RIGHT']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :LEFT or :RIGHT + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + // If left/Even page + if (isset($this->cssManager->CSS['@PAGE>>PSEUDO>>LEFT']) && $side == 'L') { + $zp = $this->cssManager->CSS['@PAGE>>PSEUDO>>LEFT']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :LEFT or :RIGHT + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + // If first page + if (isset($this->cssManager->CSS['@PAGE>>PSEUDO>>FIRST']) && $first) { + $zp = $this->cssManager->CSS['@PAGE>>PSEUDO>>FIRST']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :FIRST // mPDF 5.7.3 + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + // If named page + if ($name) { + if (isset($this->cssManager->CSS['@PAGE>>NAMED>>' . $name])) { + $zp = $this->cssManager->CSS['@PAGE>>NAMED>>' . $name]; + } else { + $zp = []; + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + if (isset($p['EVEN-HEADER-NAME']) && $oddEven == 'E') { + $p['HEADER'] = $p['EVEN-HEADER-NAME']; + unset($p['EVEN-HEADER-NAME']); + } + if (isset($p['ODD-HEADER-NAME']) && $oddEven != 'E') { + $p['HEADER'] = $p['ODD-HEADER-NAME']; + unset($p['ODD-HEADER-NAME']); + } + if (isset($p['EVEN-FOOTER-NAME']) && $oddEven == 'E') { + $p['FOOTER'] = $p['EVEN-FOOTER-NAME']; + unset($p['EVEN-FOOTER-NAME']); + } + if (isset($p['ODD-FOOTER-NAME']) && $oddEven != 'E') { + $p['FOOTER'] = $p['ODD-FOOTER-NAME']; + unset($p['ODD-FOOTER-NAME']); + } + + // If named right/Odd page + if (isset($this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>RIGHT']) && $side == 'R') { + $zp = $this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>RIGHT']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :LEFT or :RIGHT + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + // If named left/Even page + if (isset($this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>LEFT']) && $side == 'L') { + $zp = $this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>LEFT']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :LEFT or :RIGHT + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + + // If named first page + if (isset($this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>FIRST']) && $first) { + $zp = $this->cssManager->CSS['@PAGE>>NAMED>>' . $name . '>>PSEUDO>>FIRST']; + } else { + $zp = []; + } + if (isset($zp['SIZE'])) { + unset($zp['SIZE']); + } + if (isset($zp['SHEET-SIZE'])) { + unset($zp['SHEET-SIZE']); + } + // Disallow margin-left or -right on :FIRST // mPDF 5.7.3 + if (isset($zp['MARGIN-LEFT'])) { + unset($zp['MARGIN-LEFT']); + } + if (isset($zp['MARGIN-RIGHT'])) { + unset($zp['MARGIN-RIGHT']); + } + if (is_array($zp) && !empty($zp)) { + $p = array_merge($p, $zp); + } + } + + $orientation = $mgl = $mgr = $mgt = $mgb = $mgh = $mgf = ''; + $header = $footer = ''; + $resetpagenum = $pagenumstyle = $suppress = ''; + $marks = ''; + $bg = []; + + $newformat = ''; + + + if (isset($p['SHEET-SIZE']) && is_array($p['SHEET-SIZE'])) { + $newformat = $p['SHEET-SIZE']; + if ($newformat[0] > $newformat[1]) { // landscape + $newformat = array_reverse($newformat); + $p['ORIENTATION'] = 'L'; + } else { + $p['ORIENTATION'] = 'P'; + } + $this->_setPageSize($newformat, $p['ORIENTATION']); + } + + if (isset($p['SIZE']) && is_array($p['SIZE']) && !$newformat) { + if ($p['SIZE']['W'] > $p['SIZE']['H']) { + $p['ORIENTATION'] = 'L'; + } else { + $p['ORIENTATION'] = 'P'; + } + } + if (is_array($p['SIZE'])) { + if ($p['SIZE']['W'] > $this->fw) { + $p['SIZE']['W'] = $this->fw; + } // mPD 4.2 use fw not fPt + if ($p['SIZE']['H'] > $this->fh) { + $p['SIZE']['H'] = $this->fh; + } + if (($p['ORIENTATION'] == $this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION'] == 'P')) { + $outer_width_LR = ($this->fw - $p['SIZE']['W']) / 2; + $outer_width_TB = ($this->fh - $p['SIZE']['H']) / 2; + } else { + $outer_width_LR = ($this->fh - $p['SIZE']['W']) / 2; + $outer_width_TB = ($this->fw - $p['SIZE']['H']) / 2; + } + $pgw = $p['SIZE']['W']; + $pgh = $p['SIZE']['H']; + } else { // AUTO LANDSCAPE PORTRAIT + $outer_width_LR = 0; + $outer_width_TB = 0; + if (!$newformat) { + if (strtoupper($p['SIZE']) == 'AUTO') { + $p['ORIENTATION'] = $this->DefOrientation; + } elseif (strtoupper($p['SIZE']) == 'LANDSCAPE') { + $p['ORIENTATION'] = 'L'; + } else { + $p['ORIENTATION'] = 'P'; + } + } + if (($p['ORIENTATION'] == $this->DefOrientation && !$newformat) || ($newformat && $p['ORIENTATION'] == 'P')) { + $pgw = $this->fw; + $pgh = $this->fh; + } else { + $pgw = $this->fh; + $pgh = $this->fw; + } + } + + if (isset($p['HEADER']) && $p['HEADER']) { + $header = $p['HEADER']; + } + if (isset($p['FOOTER']) && $p['FOOTER']) { + $footer = $p['FOOTER']; + } + if (isset($p['RESETPAGENUM']) && $p['RESETPAGENUM']) { + $resetpagenum = $p['RESETPAGENUM']; + } + if (isset($p['PAGENUMSTYLE']) && $p['PAGENUMSTYLE']) { + $pagenumstyle = $p['PAGENUMSTYLE']; + } + if (isset($p['SUPPRESS']) && $p['SUPPRESS']) { + $suppress = $p['SUPPRESS']; + } + + if (isset($p['MARKS'])) { + if (preg_match('/cross/i', $p['MARKS']) && preg_match('/crop/i', $p['MARKS'])) { + $marks = 'CROPCROSS'; + } elseif (strtoupper($p['MARKS']) == 'CROP') { + $marks = 'CROP'; + } elseif (strtoupper($p['MARKS']) == 'CROSS') { + $marks = 'CROSS'; + } + } + + if (isset($p['BACKGROUND-COLOR']) && $p['BACKGROUND-COLOR']) { + $bg['BACKGROUND-COLOR'] = $p['BACKGROUND-COLOR']; + } + /* -- BACKGROUNDS -- */ + if (isset($p['BACKGROUND-GRADIENT']) && $p['BACKGROUND-GRADIENT']) { + $bg['BACKGROUND-GRADIENT'] = $p['BACKGROUND-GRADIENT']; + } + if (isset($p['BACKGROUND-IMAGE']) && $p['BACKGROUND-IMAGE']) { + $bg['BACKGROUND-IMAGE'] = $p['BACKGROUND-IMAGE']; + } + if (isset($p['BACKGROUND-REPEAT']) && $p['BACKGROUND-REPEAT']) { + $bg['BACKGROUND-REPEAT'] = $p['BACKGROUND-REPEAT']; + } + if (isset($p['BACKGROUND-POSITION']) && $p['BACKGROUND-POSITION']) { + $bg['BACKGROUND-POSITION'] = $p['BACKGROUND-POSITION']; + } + if (isset($p['BACKGROUND-IMAGE-RESIZE']) && $p['BACKGROUND-IMAGE-RESIZE']) { + $bg['BACKGROUND-IMAGE-RESIZE'] = $p['BACKGROUND-IMAGE-RESIZE']; + } + if (isset($p['BACKGROUND-IMAGE-OPACITY'])) { + $bg['BACKGROUND-IMAGE-OPACITY'] = $p['BACKGROUND-IMAGE-OPACITY']; + } + /* -- END BACKGROUNDS -- */ + + if (isset($p['MARGIN-LEFT'])) { + $mgl = $this->sizeConverter->convert($p['MARGIN-LEFT'], $pgw) + $outer_width_LR; + } + if (isset($p['MARGIN-RIGHT'])) { + $mgr = $this->sizeConverter->convert($p['MARGIN-RIGHT'], $pgw) + $outer_width_LR; + } + if (isset($p['MARGIN-BOTTOM'])) { + $mgb = $this->sizeConverter->convert($p['MARGIN-BOTTOM'], $pgh) + $outer_width_TB; + } + if (isset($p['MARGIN-TOP'])) { + $mgt = $this->sizeConverter->convert($p['MARGIN-TOP'], $pgh) + $outer_width_TB; + } + if (isset($p['MARGIN-HEADER'])) { + $mgh = $this->sizeConverter->convert($p['MARGIN-HEADER'], $pgh) + $outer_width_TB; + } + if (isset($p['MARGIN-FOOTER'])) { + $mgf = $this->sizeConverter->convert($p['MARGIN-FOOTER'], $pgh) + $outer_width_TB; + } + + if (isset($p['ORIENTATION']) && $p['ORIENTATION']) { + $orientation = $p['ORIENTATION']; + } + $this->page_box['outer_width_LR'] = $outer_width_LR; // Used in MARKS:crop etc. + $this->page_box['outer_width_TB'] = $outer_width_TB; + + return [$orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $header, $footer, $bg, $resetpagenum, $pagenumstyle, $suppress, $marks, $newformat]; + } + + /* -- END CSS-PAGE -- */ + + + + /* -- CSS-FLOAT -- */ + + // Added mPDF 3.0 Float DIV - CLEAR + function ClearFloats($clear, $blklvl = 0) + { + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($blklvl, true); + $end = $currpos = ($this->page * 1000 + $this->y); + if ($clear == 'BOTH' && ($l_exists || $r_exists)) { + $this->pageoutput[$this->page] = []; + $end = max($l_max, $r_max, $currpos); + } elseif ($clear == 'RIGHT' && $r_exists) { + $this->pageoutput[$this->page] = []; + $end = max($r_max, $currpos); + } elseif ($clear == 'LEFT' && $l_exists) { + $this->pageoutput[$this->page] = []; + $end = max($l_max, $currpos); + } else { + return; + } + $old_page = $this->page; + $new_page = intval($end / 1000); + if ($old_page != $new_page) { + $s = $this->PrintPageBackgrounds(); + // Writes after the marker so not overwritten later by page background etc. + $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]); + $this->pageBackgrounds = []; + $this->page = $new_page; + } + $this->ResetMargins(); + $this->pageoutput[$this->page] = []; + + $this->y = (round($end * 1000) % 1000000) / 1000; // mod changes operands to integers before processing + } + + // Added mPDF 3.0 Float DIV + function GetFloatDivInfo($blklvl = 0, $clear = false) + { + // If blklvl specified, only returns floats at that level - for ClearFloats + $l_exists = false; + $r_exists = false; + $l_max = 0; + $r_max = 0; + $l_width = 0; + $r_width = 0; + if (count($this->floatDivs)) { + $currpos = ($this->page * 1000 + $this->y); + foreach ($this->floatDivs as $f) { + if (($clear && $f['blockContext'] == $this->blk[$blklvl]['blockContext']) || (!$clear && $currpos >= $f['startpos'] && $currpos < ($f['endpos'] - 0.001) && $f['blklvl'] > $blklvl && $f['blockContext'] == $this->blk[$blklvl]['blockContext'])) { + if ($f['side'] == 'L') { + $l_exists = true; + $l_max = max($l_max, $f['endpos']); + $l_width = max($l_width, $f['w']); + } + if ($f['side'] == 'R') { + $r_exists = true; + $r_max = max($r_max, $f['endpos']); + $r_width = max($r_width, $f['w']); + } + } + } + } + return [$l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width]; + } + + /* -- END CSS-FLOAT -- */ + + // LIST MARKERS // mPDF 6 Lists + function _setListMarker($listitemtype, $listitemimage, $listitemposition) + { + // if position:inside (and NOT table) - output now as a textbuffer; (so if next is block, will move to new line) + // elseif position:outside (and NOT table) - output in front of first textbuffer output by setting listitem (cf. _saveTextBuffer) + $e = ''; + $this->listitem = ''; + $spacer = ' '; + // IMAGE + if ($listitemimage && $listitemimage != 'none') { + $listitemimage = trim(preg_replace('/url\(["\']*(.*?)["\']*\)/', '\\1', $listitemimage)); + + // ? Restrict maximum height/width of list marker?? + $maxWidth = 100; + $maxHeight = 100; + + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['visibility'] = 'visible'; + $srcpath = $listitemimage; + $orig_srcpath = $listitemimage; + + $objattr['vertical-align'] = 'BS'; // vertical alignment of marker (baseline) + $w = 0; + $h = 0; + + // Image file + $info = $this->imageProcessor->getImage($srcpath, true, true, $orig_srcpath); + if (!$info) { + return; + } + + if ($info['w'] == 0 && $info['h'] == 0) { + $info['h'] = $this->sizeConverter->convert('1em', $this->blk[$this->blklvl]['inner_width'], $this->FontSize, false); + } + + $objattr['file'] = $srcpath; + + // Default width and height calculation if needed + if ($w == 0 and $h == 0) { + /* -- IMAGES-WMF -- */ + if ($info['type'] == 'wmf') { + // WMF units are twips (1/20pt) + // divide by 20 to get points + // divide by k to get user units + $w = abs($info['w']) / (20 * Mpdf::SCALE); + $h = abs($info['h']) / (20 * Mpdf::SCALE); + } else { /* -- END IMAGES-WMF -- */ + if ($info['type'] == 'svg') { + // SVG units are pixels + $w = abs($info['w']) / Mpdf::SCALE; + $h = abs($info['h']) / Mpdf::SCALE; + } else { + // Put image at default image dpi + $w = ($info['w'] / Mpdf::SCALE) * (72 / $this->img_dpi); + $h = ($info['h'] / Mpdf::SCALE) * (72 / $this->img_dpi); + } + } + } + // IF WIDTH OR HEIGHT SPECIFIED + if ($w == 0) { + $w = abs($h * $info['w'] / $info['h']); + } + if ($h == 0) { + $h = abs($w * $info['h'] / $info['w']); + } + + if ($w > $maxWidth) { + $w = $maxWidth; + $h = abs($w * $info['h'] / $info['w']); + } + + if ($h > $maxHeight) { + $h = $maxHeight; + $w = abs($h * $info['w'] / $info['h']); + } + + $objattr['type'] = 'image'; + $objattr['itype'] = $info['type']; + + $objattr['orig_h'] = $info['h']; + $objattr['orig_w'] = $info['w']; + + /* -- IMAGES-WMF -- */ + if ($info['type'] == 'wmf') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + } else { /* -- END IMAGES-WMF -- */ + if ($info['type'] == 'svg') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + } + } + + $objattr['height'] = $h; + $objattr['width'] = $w; + $objattr['image_height'] = $h; + $objattr['image_width'] = $w; + + $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'); + $objattr['listmarker'] = true; + + $objattr['listmarkerposition'] = $listitemposition; + + $e = Mpdf::OBJECT_IDENTIFIER . "type=image,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + $this->_saveTextBuffer($e); + + if ($listitemposition == 'inside') { + $e = $spacer; + $this->_saveTextBuffer($e); + } + } elseif ($listitemtype == 'disc' || $listitemtype == 'circle' || $listitemtype == 'square') { // SYMBOL (needs new font) + $objattr = []; + $objattr['type'] = 'listmarker'; + $objattr['listmarkerposition'] = $listitemposition; + $objattr['width'] = 0; + $size = $this->sizeConverter->convert($this->list_symbol_size, $this->FontSize); + $objattr['size'] = $size; + $objattr['offset'] = $this->sizeConverter->convert($this->list_marker_offset, $this->FontSize); + + if ($listitemposition == 'inside') { + $objattr['width'] = $size + $objattr['offset']; + } + + $objattr['height'] = $this->FontSize; + $objattr['vertical-align'] = 'T'; + $objattr['text'] = ''; + $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'); + $objattr['bullet'] = $listitemtype; + $objattr['colorarray'] = $this->colorarray; + $objattr['fontfamily'] = $this->FontFamily; + $objattr['fontsize'] = $this->FontSize; + $objattr['fontsizept'] = $this->FontSizePt; + $objattr['fontstyle'] = $this->FontStyle; + + $e = Mpdf::OBJECT_IDENTIFIER . "type=listmarker,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array + + } elseif (preg_match('/U\+([a-fA-F0-9]+)/i', $listitemtype, $m)) { // SYMBOL 2 (needs new font) + + if ($this->_charDefined($this->CurrentFont['cw'], hexdec($m[1]))) { + $list_item_marker = UtfString::codeHex2utf($m[1]); + } else { + $list_item_marker = '-'; + } + if (preg_match('/rgb\(.*?\)/', $listitemtype, $m)) { + $list_item_color = $this->colorConverter->convert($m[0], $this->PDFAXwarnings); + } else { + $list_item_color = ''; + } + + // SAVE then SET COLR + $save_colorarray = $this->colorarray; + if ($list_item_color) { + $this->colorarray = $list_item_color; + } + + if ($listitemposition == 'inside') { + $e = $list_item_marker . $spacer; + $this->_saveTextBuffer($e); + } else { + $objattr = []; + $objattr['type'] = 'listmarker'; + $objattr['width'] = 0; + $objattr['height'] = $this->FontSize; + $objattr['vertical-align'] = 'T'; + $objattr['text'] = $list_item_marker; + $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'); + $objattr['colorarray'] = $this->colorarray; + $objattr['fontfamily'] = $this->FontFamily; + $objattr['fontsize'] = $this->FontSize; + $objattr['fontsizept'] = $this->FontSizePt; + $objattr['fontstyle'] = $this->FontStyle; + $e = Mpdf::OBJECT_IDENTIFIER . "type=listmarker,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array + } + + // RESET COLOR + $this->colorarray = $save_colorarray; + + } else { // TEXT + $counter = $this->listcounter[$this->listlvl]; + + if ($listitemtype == 'none') { + return; + } + + $num = $this->_getStyledNumber($counter, $listitemtype, true); + + if ($listitemposition == 'inside') { + $e = $num . $this->list_number_suffix . $spacer; + $this->_saveTextBuffer($e); + } else { + if (isset($this->blk[$this->blklvl]['direction']) && $this->blk[$this->blklvl]['direction'] == 'rtl') { + // REPLACE MIRRORED RTL $this->list_number_suffix e.g. ) -> ( (NB could use Ucdn::$mirror_pairs) + $m = strtr($this->list_number_suffix, ")]}", "([{") . $num; + } else { + $m = $num . $this->list_number_suffix; + } + + $objattr = []; + $objattr['type'] = 'listmarker'; + $objattr['width'] = 0; + $objattr['height'] = $this->FontSize; + $objattr['vertical-align'] = 'T'; + $objattr['text'] = $m; + $objattr['dir'] = (isset($this->blk[$this->blklvl]['direction']) ? $this->blk[$this->blklvl]['direction'] : 'ltr'); + $objattr['colorarray'] = $this->colorarray; + $objattr['fontfamily'] = $this->FontFamily; + $objattr['fontsize'] = $this->FontSize; + $objattr['fontsizept'] = $this->FontSizePt; + $objattr['fontstyle'] = $this->FontStyle; + $e = Mpdf::OBJECT_IDENTIFIER . "type=listmarker,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + $this->listitem = $this->_saveTextBuffer($e, '', '', true); // true returns array + } + } + } + + // mPDF Lists + function _getListMarkerWidth(&$currblk, &$a, &$i) + { + $blt_width = 0; + + $markeroffset = $this->sizeConverter->convert($this->list_marker_offset, $this->FontSize); + + // Get Maximum number in the list + $maxnum = $this->listcounter[$this->listlvl]; + if ($currblk['list_style_type'] != 'disc' && $currblk['list_style_type'] != 'circle' && $currblk['list_style_type'] != 'square') { + $lvl = 1; + for ($j = $i + 2; $j < count($a); $j+=2) { + $e = $a[$j]; + if (!$e) { + continue; + } + if ($e[0] == '/') { // end tag + $e = strtoupper(substr($e, 1)); + if ($e == 'OL' || $e == 'UL') { + if ($lvl == 1) { + break; + } + $lvl--; + } + } else { // opening tag + if (strpos($e, ' ')) { + $e = substr($e, 0, strpos($e, ' ')); + } + $e = strtoupper($e); + if ($e == 'LI') { + if ($lvl == 1) { + $maxnum++; + } + } elseif ($e == 'OL' || $e == 'UL') { + $lvl++; + } + } + } + } + + $decToAlpha = new Conversion\DecToAlpha(); + $decToRoman = new Conversion\DecToRoman(); + $decToOther = new Conversion\DecToOther($this); + + switch ($currblk['list_style_type']) { + case 'decimal': + case '1': + $blt_width = $this->GetStringWidth(str_repeat('5', strlen($maxnum)) . $this->list_number_suffix); + break; + case 'none': + $blt_width = 0; + break; + case 'upper-alpha': + case 'upper-latin': + case 'A': + $maxnumA = $decToAlpha->convert($maxnum, true); + if ($maxnum < 13) { + $blt_width = $this->GetStringWidth('D' . $this->list_number_suffix); + } else { + $blt_width = $this->GetStringWidth(str_repeat('W', strlen($maxnumA)) . $this->list_number_suffix); + } + break; + case 'lower-alpha': + case 'lower-latin': + case 'a': + $maxnuma = $decToAlpha->convert($maxnum, false); + if ($maxnum < 13) { + $blt_width = $this->GetStringWidth('b' . $this->list_number_suffix); + } else { + $blt_width = $this->GetStringWidth(str_repeat('m', strlen($maxnuma)) . $this->list_number_suffix); + } + break; + case 'upper-roman': + case 'I': + if ($maxnum > 87) { + $bbit = 87; + } elseif ($maxnum > 86) { + $bbit = 86; + } elseif ($maxnum > 37) { + $bbit = 38; + } elseif ($maxnum > 36) { + $bbit = 37; + } elseif ($maxnum > 27) { + $bbit = 28; + } elseif ($maxnum > 26) { + $bbit = 27; + } elseif ($maxnum > 17) { + $bbit = 18; + } elseif ($maxnum > 16) { + $bbit = 17; + } elseif ($maxnum > 7) { + $bbit = 8; + } elseif ($maxnum > 6) { + $bbit = 7; + } elseif ($maxnum > 3) { + $bbit = 4; + } else { + $bbit = $maxnum; + } + + $maxlnum = $decToRoman->convert($bbit, true); + $blt_width = $this->GetStringWidth($maxlnum . $this->list_number_suffix); + + break; + case 'lower-roman': + case 'i': + if ($maxnum > 87) { + $bbit = 87; + } elseif ($maxnum > 86) { + $bbit = 86; + } elseif ($maxnum > 37) { + $bbit = 38; + } elseif ($maxnum > 36) { + $bbit = 37; + } elseif ($maxnum > 27) { + $bbit = 28; + } elseif ($maxnum > 26) { + $bbit = 27; + } elseif ($maxnum > 17) { + $bbit = 18; + } elseif ($maxnum > 16) { + $bbit = 17; + } elseif ($maxnum > 7) { + $bbit = 8; + } elseif ($maxnum > 6) { + $bbit = 7; + } elseif ($maxnum > 3) { + $bbit = 4; + } else { + $bbit = $maxnum; + } + $maxlnum = $decToRoman->convert($bbit, false); + $blt_width = $this->GetStringWidth($maxlnum . $this->list_number_suffix); + break; + + case 'disc': + case 'circle': + case 'square': + $size = $this->sizeConverter->convert($this->list_symbol_size, $this->FontSize); + $offset = $this->sizeConverter->convert($this->list_marker_offset, $this->FontSize); + $blt_width = $size + $offset; + break; + + case 'arabic-indic': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0660), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'persian': + case 'urdu': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x06F0), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'bengali': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x09E6), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'devanagari': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0966), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'gujarati': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0AE6), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'gurmukhi': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0A66), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'kannada': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0CE6), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'malayalam': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(6, 0x0D66), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'oriya': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0B66), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'telugu': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(3, 0x0C66), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'tamil': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(9, 0x0BE6), strlen($maxnum)) . $this->list_number_suffix); + break; + case 'thai': + $blt_width = $this->GetStringWidth(str_repeat($decToOther->convert(5, 0x0E50), strlen($maxnum)) . $this->list_number_suffix); + break; + default: + $blt_width = $this->GetStringWidth(str_repeat('5', strlen($maxnum)) . $this->list_number_suffix); + break; + } + + return ($blt_width + $markeroffset); + } + + function _saveTextBuffer($t, $link = '', $intlink = '', $return = false) + { + // mPDF 6 Lists + $arr = []; + $arr[0] = $t; + if (isset($link) && $link) { + $arr[1] = $link; + } + $arr[2] = $this->currentfontstyle; + if (isset($this->colorarray) && $this->colorarray) { + $arr[3] = $this->colorarray; + } + $arr[4] = $this->currentfontfamily; + $arr[5] = $this->currentLang; // mPDF 6 + if (isset($intlink) && $intlink) { + $arr[7] = $intlink; + } + // mPDF 6 + // If Kerning set for OTL, and useOTL has positive value, but has not set for this particular script, + // set for kerning via kern table + // e.g. Latin script when useOTL set as 0x80 + if (isset($this->OTLtags['Plus']) && strpos($this->OTLtags['Plus'], 'kern') !== false && empty($this->OTLdata['GPOSinfo'])) { + $this->textvar = ($this->textvar | TextVars::FC_KERNING); + } + $arr[8] = $this->textvar; // mPDF 5.7.1 + if (isset($this->textparam) && $this->textparam) { + $arr[9] = $this->textparam; + } + if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) { + $arr[10] = $this->spanbgcolorarray; + } + $arr[11] = $this->currentfontsize; + if (isset($this->ReqFontStyle) && $this->ReqFontStyle) { + $arr[12] = $this->ReqFontStyle; + } + if (isset($this->lSpacingCSS) && $this->lSpacingCSS) { + $arr[14] = $this->lSpacingCSS; + } + if (isset($this->wSpacingCSS) && $this->wSpacingCSS) { + $arr[15] = $this->wSpacingCSS; + } + if (isset($this->spanborddet) && $this->spanborddet) { + $arr[16] = $this->spanborddet; + } + if (isset($this->textshadow) && $this->textshadow) { + $arr[17] = $this->textshadow; + } + if (isset($this->OTLdata) && $this->OTLdata) { + $arr[18] = $this->OTLdata; + $this->OTLdata = []; + } // mPDF 5.7.1 + else { + $arr[18] = null; + } + // mPDF 6 Lists + if ($return) { + return ($arr); + } + if ($this->listitem) { + $this->textbuffer[] = $this->listitem; + $this->listitem = []; + } + $this->textbuffer[] = $arr; + } + + function _saveCellTextBuffer($t, $link = '', $intlink = '') + { + $arr = []; + $arr[0] = $t; + if (isset($link) && $link) { + $arr[1] = $link; + } + $arr[2] = $this->currentfontstyle; + if (isset($this->colorarray) && $this->colorarray) { + $arr[3] = $this->colorarray; + } + $arr[4] = $this->currentfontfamily; + if (isset($intlink) && $intlink) { + $arr[7] = $intlink; + } + // mPDF 6 + // If Kerning set for OTL, and useOTL has positive value, but has not set for this particular script, + // set for kerning via kern table + // e.g. Latin script when useOTL set as 0x80 + if (isset($this->OTLtags['Plus']) && strpos($this->OTLtags['Plus'], 'kern') !== false && empty($this->OTLdata['GPOSinfo'])) { + $this->textvar = ($this->textvar | TextVars::FC_KERNING); + } + $arr[8] = $this->textvar; // mPDF 5.7.1 + if (isset($this->textparam) && $this->textparam) { + $arr[9] = $this->textparam; + } + if (isset($this->spanbgcolorarray) && $this->spanbgcolorarray) { + $arr[10] = $this->spanbgcolorarray; + } + $arr[11] = $this->currentfontsize; + if (isset($this->ReqFontStyle) && $this->ReqFontStyle) { + $arr[12] = $this->ReqFontStyle; + } + if (isset($this->lSpacingCSS) && $this->lSpacingCSS) { + $arr[14] = $this->lSpacingCSS; + } + if (isset($this->wSpacingCSS) && $this->wSpacingCSS) { + $arr[15] = $this->wSpacingCSS; + } + if (isset($this->spanborddet) && $this->spanborddet) { + $arr[16] = $this->spanborddet; + } + if (isset($this->textshadow) && $this->textshadow) { + $arr[17] = $this->textshadow; + } + if (isset($this->OTLdata) && $this->OTLdata) { + $arr[18] = $this->OTLdata; + $this->OTLdata = []; + } // mPDF 5.7.1 + else { + $arr[18] = null; + } + $this->cell[$this->row][$this->col]['textbuffer'][] = $arr; + } + + function printbuffer($arrayaux, $blockstate = 0, $is_table = false, $table_draft = false, $cell_dir = '') + { + // $blockstate = 0; // NO margins/padding + // $blockstate = 1; // Top margins/padding only + // $blockstate = 2; // Bottom margins/padding only + // $blockstate = 3; // Top & bottom margins/padding + $this->spanbgcolorarray = ''; + $this->spanbgcolor = false; + $this->spanborder = false; + $this->spanborddet = []; + $paint_ht_corr = 0; + /* -- CSS-FLOAT -- */ + if (count($this->floatDivs)) { + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->GetFloatDivInfo($this->blklvl); + if (($this->blk[$this->blklvl]['inner_width'] - $l_width - $r_width) < (2 * $this->GetCharWidth('W', false))) { + // Too narrow to fit - try to move down past L or R float + if ($l_max < $r_max && ($this->blk[$this->blklvl]['inner_width'] - $r_width) > (2 * $this->GetCharWidth('W', false))) { + $this->ClearFloats('LEFT', $this->blklvl); + } elseif ($r_max < $l_max && ($this->blk[$this->blklvl]['inner_width'] - $l_width) > (2 * $this->GetCharWidth('W', false))) { + $this->ClearFloats('RIGHT', $this->blklvl); + } else { + $this->ClearFloats('BOTH', $this->blklvl); + } + } + } + /* -- END CSS-FLOAT -- */ + $bak_y = $this->y; + $bak_x = $this->x; + $align = ''; + if (!$is_table) { + if (isset($this->blk[$this->blklvl]['align']) && $this->blk[$this->blklvl]['align']) { + $align = $this->blk[$this->blklvl]['align']; + } + // Block-align is set by e.g. <.. align="center"> Takes priority for this block but not inherited + if (isset($this->blk[$this->blklvl]['block-align']) && $this->blk[$this->blklvl]['block-align']) { + $align = $this->blk[$this->blklvl]['block-align']; + } + if (isset($this->blk[$this->blklvl]['direction'])) { + $blockdir = $this->blk[$this->blklvl]['direction']; + } else { + $blockdir = ""; + } + $this->divwidth = $this->blk[$this->blklvl]['width']; + } else { + $align = $this->cellTextAlign; + $blockdir = $cell_dir; + } + $oldpage = $this->page; + + // ADDED for Out of Block now done as Flowing Block + if ($this->divwidth == 0) { + $this->divwidth = $this->pgwidth; + } + + if (!$is_table) { + $this->SetLineHeight($this->FontSizePt, $this->blk[$this->blklvl]['line_height']); + } + $this->divheight = $this->lineheight; + $old_height = $this->divheight; + + // As a failsafe - if font has been set but not output to page + if (!$table_draft) { + $this->SetFont($this->default_font, '', $this->default_font_size, true, true); // force output to page + } + + $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, true, $blockdir, $table_draft); + + $array_size = count($arrayaux); + + // Added - Otherwise

did not output top margins/padding for 1st/2nd div + if ($array_size == 0) { + $this->finishFlowingBlock(true); + } // true = END of flowing block + // mPDF 6 + // ALL the chunks of textbuffer need to have at least basic OTLdata set + // First make sure each element/chunk has the OTLdata for Bidi set. + for ($i = 0; $i < $array_size; $i++) { + if (empty($arrayaux[$i][18])) { + if (substr($arrayaux[$i][0], 0, 3) == Mpdf::OBJECT_IDENTIFIER) { // object identifier has been identified! + $unicode = [0xFFFC]; // Object replacement character + } else { + $unicode = $this->UTF8StringToArray($arrayaux[$i][0], false); + } + $is_strong = false; + $this->getBasicOTLdata($arrayaux[$i][18], $unicode, $is_strong); + } + // Gets messed up if try and use core fonts inside a paragraph of text which needs to be BiDi re-ordered or OTLdata set + if (($blockdir == 'rtl' || $this->biDirectional) && isset($arrayaux[$i][4]) && in_array($arrayaux[$i][4], ['ccourier', 'ctimes', 'chelvetica', 'csymbol', 'czapfdingbats'])) { + throw new \Mpdf\MpdfException("You cannot use core fonts in a document which contains RTL text."); + } + } + // mPDF 6 + // Process bidirectional text ready for bidi-re-ordering (which is done after line-breaks are established in WriteFlowingBlock etc.) + if (($blockdir == 'rtl' || $this->biDirectional) && !$table_draft) { + if (empty($this->otl)) { + $this->otl = new Otl($this, $this->fontCache); + } + $this->otl->bidiPrepare($arrayaux, $blockdir); + $array_size = count($arrayaux); + } + + // Remove empty items // mPDF 6 + for ($i = $array_size - 1; $i > 0; $i--) { + if ('' === $arrayaux[$i][0] && (isset($arrayaux[$i][16]) && $arrayaux[$i][16] !== '0') && empty($arrayaux[$i][7])) { + unset($arrayaux[$i]); + } + } + + // Correct adjoining borders for inline elements + if (isset($arrayaux[0][16])) { + $lastspanborder = $arrayaux[0][16]; + } else { + $lastspanborder = false; + } + for ($i = 1; $i < $array_size; $i++) { + if (isset($arrayaux[$i][16]) && $arrayaux[$i][16] == $lastspanborder && + ((!isset($arrayaux[$i][9]['bord-decoration']) && !isset($arrayaux[$i - 1][9]['bord-decoration'])) || + (isset($arrayaux[$i][9]['bord-decoration']) && isset($arrayaux[$i - 1][9]['bord-decoration']) && $arrayaux[$i][9]['bord-decoration'] == $arrayaux[$i - 1][9]['bord-decoration']) + ) + ) { + if (isset($arrayaux[$i][16]['R'])) { + $lastspanborder = $arrayaux[$i][16]; + } else { + $lastspanborder = false; + } + $arrayaux[$i][16]['L']['s'] = 0; + $arrayaux[$i][16]['L']['w'] = 0; + $arrayaux[$i - 1][16]['R']['s'] = 0; + $arrayaux[$i - 1][16]['R']['w'] = 0; + } else { + if (isset($arrayaux[$i][16]['R'])) { + $lastspanborder = $arrayaux[$i][16]; + } else { + $lastspanborder = false; + } + } + } + + for ($i = 0; $i < $array_size; $i++) { + // COLS + $oldcolumn = $this->CurrCol; + $vetor = isset($arrayaux[$i]) ? $arrayaux[$i] : null; + if ($i == 0 && $vetor[0] != "\n" && ! $this->ispre) { + $vetor[0] = ltrim($vetor[0]); + if (!empty($vetor[18])) { + $this->otl->trimOTLdata($vetor[18], true, false); + } // *OTL* + } + + // FIXED TO ALLOW IT TO SHOW '0' + if (empty($vetor[0]) && !($vetor[0] === '0') && empty($vetor[7])) { + // Ignore empty text and not carrying an internal link + // Check if it is the last element. If so then finish printing the block + if ($i == ($array_size - 1)) { + $this->finishFlowingBlock(true); + } // true = END of flowing block + continue; + } + + + // Activating buffer properties + if (isset($vetor[11]) && $vetor[11] != '') { // Font Size + if ($is_table && $this->shrin_k) { + $this->SetFontSize($vetor[11] / $this->shrin_k, false); + } else { + $this->SetFontSize($vetor[11], false); + } + } + + if (isset($vetor[17]) && !empty($vetor[17])) { // TextShadow + $this->textshadow = $vetor[17]; + } + if (isset($vetor[16]) && !empty($vetor[16])) { // Border + $this->spanborddet = $vetor[16]; + $this->spanborder = true; + } + + if (isset($vetor[15])) { // Word spacing + $this->wSpacingCSS = $vetor[15]; + if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') { + $this->minwSpacing = $this->sizeConverter->convert($this->wSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 + } + } + if (isset($vetor[14])) { // Letter spacing + $this->lSpacingCSS = $vetor[14]; + if (($this->lSpacingCSS || $this->lSpacingCSS === '0') && strtoupper($this->lSpacingCSS) != 'NORMAL') { + $this->fixedlSpacing = $this->sizeConverter->convert($this->lSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 + } + } + + + if (isset($vetor[10]) and ! empty($vetor[10])) { // Background color + $this->spanbgcolorarray = $vetor[10]; + $this->spanbgcolor = true; + } + if (isset($vetor[9]) and ! empty($vetor[9])) { // Text parameters - Outline + hyphens + $this->textparam = $vetor[9]; + $this->SetTextOutline($this->textparam); + // mPDF 5.7.3 inline text-decoration parameters + if ($is_table && $this->shrin_k) { + if (isset($this->textparam['text-baseline'])) { + $this->textparam['text-baseline'] /= $this->shrin_k; + } + if (isset($this->textparam['decoration-baseline'])) { + $this->textparam['decoration-baseline'] /= $this->shrin_k; + } + if (isset($this->textparam['decoration-fontsize'])) { + $this->textparam['decoration-fontsize'] /= $this->shrin_k; + } + } + } + if (isset($vetor[8])) { // mPDF 5.7.1 + $this->textvar = $vetor[8]; + } + if (isset($vetor[7]) and $vetor[7] != '') { // internal target: + $ily = $this->y; + if ($this->table_rotate) { + $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "tbrot" => true]; + } elseif ($this->kwt) { + $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "kwt" => true]; + } elseif ($this->ColActive) { + $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page, "col" => $this->CurrCol]; + } elseif (!$this->keep_block_together) { + $this->internallink[$vetor[7]] = ["Y" => $ily, "PAGE" => $this->page]; + } + if (empty($vetor[0])) { // Ignore empty text + // Check if it is the last element. If so then finish printing the block + if ($i == ($array_size - 1)) { + $this->finishFlowingBlock(true); + } // true = END of flowing block + continue; + } + } + if (isset($vetor[5]) and $vetor[5] != '') { // Language // mPDF 6 + $this->currentLang = $vetor[5]; + } + if (isset($vetor[4]) and $vetor[4] != '') { // Font Family + $font = $this->SetFont($vetor[4], $this->FontStyle, 0, false); + } + if (!empty($vetor[3])) { // Font Color + $cor = $vetor[3]; + $this->SetTColor($cor); + } + if (isset($vetor[2]) and $vetor[2] != '') { // Bold,Italic styles + $this->SetStyles($vetor[2]); + } + + if (isset($vetor[12]) and $vetor[12] != '') { // Requested Bold,Italic + $this->ReqFontStyle = $vetor[12]; + } + if (isset($vetor[1]) and $vetor[1] != '') { // LINK + if (strpos($vetor[1], ".") === false && strpos($vetor[1], "@") !== 0) { // assuming every external link has a dot indicating extension (e.g: .html .txt .zip www.somewhere.com etc.) + // Repeated reference to same anchor? + while (array_key_exists($vetor[1], $this->internallink)) { + $vetor[1] = "#" . $vetor[1]; + } + $this->internallink[$vetor[1]] = $this->AddLink(); + $vetor[1] = $this->internallink[$vetor[1]]; + } + $this->HREF = $vetor[1]; // HREF link style set here ****** + } + + // SPECIAL CONTENT - IMAGES & FORM OBJECTS + // Print-out special content + + if (substr($vetor[0], 0, 3) == Mpdf::OBJECT_IDENTIFIER) { // identifier has been identified! + $objattr = $this->_getObjAttr($vetor[0]); + + /* -- TABLES -- */ + if ($objattr['type'] == 'nestedtable') { + if ($objattr['nestedcontent']) { + $level = $objattr['level']; + $table = &$this->table[$level][$objattr['table']]; + + if ($table_draft) { + $this->y += $this->table[($level + 1)][$objattr['nestedcontent']]['h']; // nested table height + $this->finishFlowingBlock(false, 'nestedtable'); + } else { + $cell = &$table['cells'][$objattr['row']][$objattr['col']]; + $this->finishFlowingBlock(false, 'nestedtable'); + $save_dw = $this->divwidth; + $save_buffer = $this->cellBorderBuffer; + $this->cellBorderBuffer = []; + $ncx = $this->x; + list($dummyx, $w) = $this->_tableGetWidth($table, $objattr['row'], $objattr['col']); + $ntw = $this->table[($level + 1)][$objattr['nestedcontent']]['w']; // nested table width + if (!$this->simpleTables) { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($cell['borderbin']); + } else { + $br = $cell['border_details']['R']['w']; + $bl = $cell['border_details']['L']['w']; + } + if ($table['borders_separate']) { + $innerw = $w - $bl - $br - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H']; + } else { + $innerw = $w - $bl / 2 - $br / 2 - $cell['padding']['L'] - $cell['padding']['R']; + } + } elseif ($this->simpleTables) { + if ($table['borders_separate']) { + $innerw = $w - $table['simple']['border_details']['L']['w'] - $table['simple']['border_details']['R']['w'] - $cell['padding']['L'] - $cell['padding']['R'] - $table['border_spacing_H']; + } else { + $innerw = $w - $table['simple']['border_details']['L']['w'] / 2 - $table['simple']['border_details']['R']['w'] / 2 - $cell['padding']['L'] - $cell['padding']['R']; + } + } + if ($cell['a'] == 'C' || $this->table[($level + 1)][$objattr['nestedcontent']]['a'] == 'C') { + $ncx += ($innerw - $ntw) / 2; + } elseif ($cell['a'] == 'R' || $this->table[($level + 1)][$objattr['nestedcontent']]['a'] == 'R') { + $ncx += $innerw - $ntw; + } + $this->x = $ncx; + + $this->_tableWrite($this->table[($level + 1)][$objattr['nestedcontent']]); + $this->cellBorderBuffer = $save_buffer; + $this->x = $bak_x; + $this->divwidth = $save_dw; + } + + $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); + } + } else { + /* -- END TABLES -- */ + if ($is_table) { // *TABLES* + $maxWidth = $this->divwidth; // *TABLES* + } // *TABLES* + else { // *TABLES* + $maxWidth = $this->divwidth - ($this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_right'] + $this->blk[$this->blklvl]['border_right']['w']); + } // *TABLES* + + /* -- CSS-IMAGE-FLOAT -- */ + // If float (already) exists at this level + if (isset($this->floatmargins['R']) && $this->y <= $this->floatmargins['R']['y1'] && $this->y >= $this->floatmargins['R']['y0']) { + $maxWidth -= $this->floatmargins['R']['w']; + } + if (isset($this->floatmargins['L']) && $this->y <= $this->floatmargins['L']['y1'] && $this->y >= $this->floatmargins['L']['y0']) { + $maxWidth -= $this->floatmargins['L']['w']; + } + /* -- END CSS-IMAGE-FLOAT -- */ + + list($skipln) = $this->inlineObject($objattr['type'], '', $this->y, $objattr, $this->lMargin, ($this->flowingBlockAttr['contentWidth'] / Mpdf::SCALE), $maxWidth, $this->flowingBlockAttr['height'], false, $is_table); + // 1 -> New line needed because of width + // -1 -> Will fit width on line but NEW PAGE REQUIRED because of height + // -2 -> Will not fit on line therefore needs new line but thus NEW PAGE REQUIRED + $iby = $this->y; + $oldpage = $this->page; + $oldcol = $this->CurrCol; + if (($skipln == 1 || $skipln == -2) && !isset($objattr['float'])) { + $this->finishFlowingBlock(false, $objattr['type']); + $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); + } + + if (!$table_draft) { + $thispage = $this->page; + if ($this->CurrCol != $oldcol) { + $changedcol = true; + } else { + $changedcol = false; + } + + // the previous lines can already have triggered page break or column change + if (!$changedcol && $skipln < 0 && $this->AcceptPageBreak() && $thispage == $oldpage) { + $this->AddPage($this->CurOrientation); + + // Added to correct Images already set on line before page advanced + // i.e. if second inline image on line is higher than first and forces new page + if (count($this->objectbuffer)) { + $yadj = $iby - $this->y; + foreach ($this->objectbuffer as $ib => $val) { + if ($this->objectbuffer[$ib]['OUTER-Y']) { + $this->objectbuffer[$ib]['OUTER-Y'] -= $yadj; + } + if ($this->objectbuffer[$ib]['BORDER-Y']) { + $this->objectbuffer[$ib]['BORDER-Y'] -= $yadj; + } + if ($this->objectbuffer[$ib]['INNER-Y']) { + $this->objectbuffer[$ib]['INNER-Y'] -= $yadj; + } + } + } + } + + // Added to correct for OddEven Margins + if ($this->page != $oldpage) { + if (($this->page - $oldpage) % 2 == 1) { + $bak_x += $this->MarginCorrection; + } + $oldpage = $this->page; + $y = $this->tMargin - $paint_ht_corr; + $this->oldy = $this->tMargin - $paint_ht_corr; + $old_height = 0; + } + $this->x = $bak_x; + /* -- COLUMNS -- */ + // COLS + // OR COLUMN CHANGE + if ($this->CurrCol != $oldcolumn) { + if ($this->directionality == 'rtl') { // *OTL* + $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* + } // *OTL* + else { // *OTL* + $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); + } // *OTL* + $this->x = $bak_x; + $oldcolumn = $this->CurrCol; + $y = $this->y0 - $paint_ht_corr; + $this->oldy = $this->y0 - $paint_ht_corr; + $old_height = 0; + } + /* -- END COLUMNS -- */ + } + + /* -- CSS-IMAGE-FLOAT -- */ + if ($objattr['type'] == 'image' && isset($objattr['float'])) { + $fy = $this->y; + + // DIV TOP MARGIN/BORDER/PADDING + if ($this->flowingBlockAttr['newblock'] && ($this->flowingBlockAttr['blockstate'] == 1 || $this->flowingBlockAttr['blockstate'] == 3) && $this->flowingBlockAttr['lineCount'] == 0) { + $fy += $this->blk[$this->blklvl]['margin_top'] + $this->blk[$this->blklvl]['padding_top'] + $this->blk[$this->blklvl]['border_top']['w']; + } + + if ($objattr['float'] == 'R') { + $fx = $this->w - $this->rMargin - $objattr['width'] - ($this->blk[$this->blklvl]['outer_right_margin'] + $this->blk[$this->blklvl]['border_right']['w'] + $this->blk[$this->blklvl]['padding_right']); + } elseif ($objattr['float'] == 'L') { + $fx = $this->lMargin + ($this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left']); + } + $w = $objattr['width']; + $h = abs($objattr['height']); + + $widthLeft = $maxWidth - ($this->flowingBlockAttr['contentWidth'] / Mpdf::SCALE); + $maxHeight = $this->h - ($this->tMargin + $this->margin_header + $this->bMargin + 10); + // For Images + $extraWidth = ($objattr['border_left']['w'] + $objattr['border_right']['w'] + $objattr['margin_left'] + $objattr['margin_right']); + $extraHeight = ($objattr['border_top']['w'] + $objattr['border_bottom']['w'] + $objattr['margin_top'] + $objattr['margin_bottom']); + + if ($objattr['itype'] == 'wmf' || $objattr['itype'] == 'svg') { + $file = $objattr['file']; + $info = $this->formobjects[$file]; + } else { + $file = $objattr['file']; + $info = $this->images[$file]; + } + $img_w = $w - $extraWidth; + $img_h = $h - $extraHeight; + if ($objattr['border_left']['w']) { + $objattr['BORDER-WIDTH'] = $img_w + (($objattr['border_left']['w'] + $objattr['border_right']['w']) / 2); + $objattr['BORDER-HEIGHT'] = $img_h + (($objattr['border_top']['w'] + $objattr['border_bottom']['w']) / 2); + $objattr['BORDER-X'] = $fx + $objattr['margin_left'] + (($objattr['border_left']['w']) / 2); + $objattr['BORDER-Y'] = $fy + $objattr['margin_top'] + (($objattr['border_top']['w']) / 2); + } + $objattr['INNER-WIDTH'] = $img_w; + $objattr['INNER-HEIGHT'] = $img_h; + $objattr['INNER-X'] = $fx + $objattr['margin_left'] + ($objattr['border_left']['w']); + $objattr['INNER-Y'] = $fy + $objattr['margin_top'] + ($objattr['border_top']['w']); + $objattr['ID'] = $info['i']; + $objattr['OUTER-WIDTH'] = $w; + $objattr['OUTER-HEIGHT'] = $h; + $objattr['OUTER-X'] = $fx; + $objattr['OUTER-Y'] = $fy; + if ($objattr['float'] == 'R') { + // If R float already exists at this level + $this->floatmargins['R']['skipline'] = false; + if (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) { + $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 + } // If L float already exists at this level + elseif (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) { + // Final check distance between floats is not now too narrow to fit text + $mw = 2 * $this->GetCharWidth('W', false); + if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['L']['w']) < $mw) { + $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 + } else { + $this->floatmargins['R']['x'] = $fx; + $this->floatmargins['R']['w'] = $w; + $this->floatmargins['R']['y0'] = $fy; + $this->floatmargins['R']['y1'] = $fy + $h; + if ($skipln == 1) { + $this->floatmargins['R']['skipline'] = true; + $this->floatmargins['R']['id'] = count($this->floatbuffer) + 0; + $objattr['skipline'] = true; + } + $this->floatbuffer[] = $objattr; + } + } else { + $this->floatmargins['R']['x'] = $fx; + $this->floatmargins['R']['w'] = $w; + $this->floatmargins['R']['y0'] = $fy; + $this->floatmargins['R']['y1'] = $fy + $h; + if ($skipln == 1) { + $this->floatmargins['R']['skipline'] = true; + $this->floatmargins['R']['id'] = count($this->floatbuffer) + 0; + $objattr['skipline'] = true; + } + $this->floatbuffer[] = $objattr; + } + } elseif ($objattr['float'] == 'L') { + // If L float already exists at this level + $this->floatmargins['L']['skipline'] = false; + if (isset($this->floatmargins['L']['y1']) && $this->floatmargins['L']['y1'] > 0 && $fy < $this->floatmargins['L']['y1']) { + $this->floatmargins['L']['skipline'] = false; + $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 + } // If R float already exists at this level + elseif (isset($this->floatmargins['R']['y1']) && $this->floatmargins['R']['y1'] > 0 && $fy < $this->floatmargins['R']['y1']) { + // Final check distance between floats is not now too narrow to fit text + $mw = 2 * $this->GetCharWidth('W', false); + if (($this->blk[$this->blklvl]['inner_width'] - $w - $this->floatmargins['R']['w']) < $mw) { + $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 + } else { + $this->floatmargins['L']['x'] = $fx + $w; + $this->floatmargins['L']['w'] = $w; + $this->floatmargins['L']['y0'] = $fy; + $this->floatmargins['L']['y1'] = $fy + $h; + if ($skipln == 1) { + $this->floatmargins['L']['skipline'] = true; + $this->floatmargins['L']['id'] = count($this->floatbuffer) + 0; + $objattr['skipline'] = true; + } + $this->floatbuffer[] = $objattr; + } + } else { + $this->floatmargins['L']['x'] = $fx + $w; + $this->floatmargins['L']['w'] = $w; + $this->floatmargins['L']['y0'] = $fy; + $this->floatmargins['L']['y1'] = $fy + $h; + if ($skipln == 1) { + $this->floatmargins['L']['skipline'] = true; + $this->floatmargins['L']['id'] = count($this->floatbuffer) + 0; + $objattr['skipline'] = true; + } + $this->floatbuffer[] = $objattr; + } + } + } else { + /* -- END CSS-IMAGE-FLOAT -- */ + $this->WriteFlowingBlock($vetor[0], (isset($vetor[18]) ? $vetor[18] : null)); // mPDF 5.7.1 + /* -- CSS-IMAGE-FLOAT -- */ + } + /* -- END CSS-IMAGE-FLOAT -- */ + } // *TABLES* + } // END If special content + else { // THE text + if ($this->tableLevel) { + $paint_ht_corr = 0; + } // To move the y up when new column/page started if div border needed + else { + $paint_ht_corr = $this->blk[$this->blklvl]['border_top']['w']; + } + + if ($vetor[0] == "\n") { // We are reading a
now turned into newline ("\n") + if ($this->flowingBlockAttr['content']) { + $this->finishFlowingBlock(false, 'br'); + } elseif ($is_table) { + $this->y+= $this->_computeLineheight($this->cellLineHeight); + } elseif (!$is_table) { + $this->DivLn($this->lineheight); + if ($this->ColActive) { + $this->breakpoints[$this->CurrCol][] = $this->y; + } // *COLUMNS* + } + // Added to correct for OddEven Margins + if ($this->page != $oldpage) { + if (($this->page - $oldpage) % 2 == 1) { + $bak_x += $this->MarginCorrection; + } + $oldpage = $this->page; + $y = $this->tMargin - $paint_ht_corr; + $this->oldy = $this->tMargin - $paint_ht_corr; + $old_height = 0; + } + $this->x = $bak_x; + /* -- COLUMNS -- */ + // COLS + // OR COLUMN CHANGE + if ($this->CurrCol != $oldcolumn) { + if ($this->directionality == 'rtl') { // *OTL* + $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* + } // *OTL* + else { // *OTL* + $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); + } // *OTL* + $this->x = $bak_x; + $oldcolumn = $this->CurrCol; + $y = $this->y0 - $paint_ht_corr; + $this->oldy = $this->y0 - $paint_ht_corr; + $old_height = 0; + } + /* -- END COLUMNS -- */ + $this->newFlowingBlock($this->divwidth, $this->divheight, $align, $is_table, $blockstate, false, $blockdir, $table_draft); + } else { + $this->WriteFlowingBlock($vetor[0], $vetor[18]); // mPDF 5.7.1 + // Added to correct for OddEven Margins + if ($this->page != $oldpage) { + if (($this->page - $oldpage) % 2 == 1) { + $bak_x += $this->MarginCorrection; + $this->x = $bak_x; + } + $oldpage = $this->page; + $y = $this->tMargin - $paint_ht_corr; + $this->oldy = $this->tMargin - $paint_ht_corr; + $old_height = 0; + } + /* -- COLUMNS -- */ + // COLS + // OR COLUMN CHANGE + if ($this->CurrCol != $oldcolumn) { + if ($this->directionality == 'rtl') { // *OTL* + $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* + } // *OTL* + else { // *OTL* + $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); + } // *OTL* + $this->x = $bak_x; + $oldcolumn = $this->CurrCol; + $y = $this->y0 - $paint_ht_corr; + $this->oldy = $this->y0 - $paint_ht_corr; + $old_height = 0; + } + /* -- END COLUMNS -- */ + } + } + + // Check if it is the last element. If so then finish printing the block + if ($i == ($array_size - 1)) { + $this->finishFlowingBlock(true); // true = END of flowing block + // Added to correct for OddEven Margins + if ($this->page != $oldpage) { + if (($this->page - $oldpage) % 2 == 1) { + $bak_x += $this->MarginCorrection; + $this->x = $bak_x; + } + $oldpage = $this->page; + $y = $this->tMargin - $paint_ht_corr; + $this->oldy = $this->tMargin - $paint_ht_corr; + $old_height = 0; + } + + /* -- COLUMNS -- */ + // COLS + // OR COLUMN CHANGE + if ($this->CurrCol != $oldcolumn) { + if ($this->directionality == 'rtl') { // *OTL* + $bak_x -= ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); // *OTL* + } // *OTL* + else { // *OTL* + $bak_x += ($this->CurrCol - $oldcolumn) * ($this->ColWidth + $this->ColGap); + } // *OTL* + $this->x = $bak_x; + $oldcolumn = $this->CurrCol; + $y = $this->y0 - $paint_ht_corr; + $this->oldy = $this->y0 - $paint_ht_corr; + $old_height = 0; + } + /* -- END COLUMNS -- */ + } + + // RESETTING VALUES + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + $this->colorarray = ''; + $this->spanbgcolorarray = ''; + $this->spanbgcolor = false; + $this->spanborder = false; + $this->spanborddet = []; + $this->HREF = ''; + $this->textparam = []; + $this->SetTextOutline(); + + $this->textvar = 0x00; // mPDF 5.7.1 + $this->OTLtags = []; + $this->textshadow = ''; + + $this->currentfontfamily = ''; + $this->currentfontsize = ''; + $this->currentfontstyle = ''; + $this->currentLang = $this->default_lang; // mPDF 6 + $this->RestrictUnicodeFonts($this->default_available_fonts); // mPDF 6 + /* -- TABLES -- */ + if ($this->tableLevel) { + $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); // *TABLES* + } else { /* -- END TABLES -- */ + if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) { + $this->SetLineHeight('', $this->blk[$this->blklvl]['line_height']); // sets default line height + } + } + $this->ResetStyles(); + $this->lSpacingCSS = ''; + $this->wSpacingCSS = ''; + $this->fixedlSpacing = false; + $this->minwSpacing = 0; + $this->SetDash(); + $this->dash_on = false; + $this->dotted_on = false; + }//end of for(i=0;iReset(); // mPDF 6 + // PAINT DIV BORDER // DISABLED IN COLUMNS AS DOESN'T WORK WHEN BROKEN ACROSS COLS?? + if ((isset($this->blk[$this->blklvl]['border']) || isset($this->blk[$this->blklvl]['bgcolor']) || isset($this->blk[$this->blklvl]['box_shadow'])) && $blockstate && ($this->y != $this->oldy)) { + $bottom_y = $this->y; // Does not include Bottom Margin + if (isset($this->blk[$this->blklvl]['startpage']) && $this->blk[$this->blklvl]['startpage'] != $this->page && $blockstate != 1) { + $this->PaintDivBB('pagetop', $blockstate); + } elseif ($blockstate != 1) { + $this->PaintDivBB('', $blockstate); + } + $this->y = $bottom_y; + $this->x = $bak_x; + } + + // Reset Font + $this->SetFontSize($this->default_font_size, false); + if ($table_draft) { + $ch = $this->y - $bak_y; + $this->y = $bak_y; + $this->x = $bak_x; + return $ch; + } + } + + function _setDashBorder($style, $div, $cp, $side) + { + if ($style == 'dashed' && (($side == 'L' || $side == 'R') || ($side == 'T' && $div != 'pagetop' && !$cp) || ($side == 'B' && $div != 'pagebottom') )) { + $dashsize = 2; // final dash will be this + 1*linewidth + $dashsizek = 1.5; // ratio of Dash/Blank + $this->SetDash($dashsize, ($dashsize / $dashsizek) + ($this->LineWidth * 2)); + } elseif ($style == 'dotted' || ($side == 'T' && ($div == 'pagetop' || $cp)) || ($side == 'B' && $div == 'pagebottom')) { + // Round join and cap + $this->SetLineJoin(1); + $this->SetLineCap(1); + $this->SetDash(0.001, ($this->LineWidth * 3)); + } + } + + function _setBorderLine($b, $k = 1) + { + $this->SetLineWidth($b['w'] / $k); + $this->SetDColor($b['c']); + if ($b['c'][0] == 5) { // RGBa + $this->SetAlpha(ord($b['c'][4]) / 100, 'Normal', false, 'S'); // mPDF 5.7.2 + } elseif ($b['c'][0] == 6) { // CMYKa + $this->SetAlpha(ord($b['c'][5]) / 100, 'Normal', false, 'S'); // mPDF 5.7.2 + } + } + + function PaintDivBB($divider = '', $blockstate = 0, $blvl = 0) + { + // Borders & backgrounds are done elsewhere for columns - messes up the repositioning in printcolumnbuffer + if ($this->ColActive) { + return; + } // *COLUMNS* + if ($this->keep_block_together) { + return; + } // mPDF 6 + $save_y = $this->y; + if (!$blvl) { + $blvl = $this->blklvl; + } + $x0 = $x1 = $y0 = $y1 = 0; + + // Added mPDF 3.0 Float DIV + if (isset($this->blk[$blvl]['bb_painted'][$this->page]) && $this->blk[$blvl]['bb_painted'][$this->page]) { + return; + } // *CSS-FLOAT* + + if (isset($this->blk[$blvl]['x0'])) { + $x0 = $this->blk[$blvl]['x0']; + } // left + if (isset($this->blk[$blvl]['y1'])) { + $y1 = $this->blk[$blvl]['y1']; + } // bottom + // Added mPDF 3.0 Float DIV - ensures backgrounds/borders are drawn to bottom of page + if ($y1 == 0) { + if ($divider == 'pagebottom') { + $y1 = $this->h - $this->bMargin; + } else { + $y1 = $this->y; + } + } + + $continuingpage = (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page); + + if (isset($this->blk[$blvl]['y0'])) { + $y0 = $this->blk[$blvl]['y0']; + } + $h = $y1 - $y0; + $w = $this->blk[$blvl]['width']; + $x1 = $x0 + $w; + + // Set border-widths as used here + $border_top = $this->blk[$blvl]['border_top']['w']; + $border_bottom = $this->blk[$blvl]['border_bottom']['w']; + $border_left = $this->blk[$blvl]['border_left']['w']; + $border_right = $this->blk[$blvl]['border_right']['w']; + if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) { + $border_top = 0; + } + if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') { + $border_bottom = 0; + } + + $brTL_H = 0; + $brTL_V = 0; + $brTR_H = 0; + $brTR_V = 0; + $brBL_H = 0; + $brBL_V = 0; + $brBR_H = 0; + $brBR_V = 0; + + $brset = false; + /* -- BORDER-RADIUS -- */ + if (isset($this->blk[$blvl]['border_radius_TL_H'])) { + $brTL_H = $this->blk[$blvl]['border_radius_TL_H']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_TL_V'])) { + $brTL_V = $this->blk[$blvl]['border_radius_TL_V']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_TR_H'])) { + $brTR_H = $this->blk[$blvl]['border_radius_TR_H']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_TR_V'])) { + $brTR_V = $this->blk[$blvl]['border_radius_TR_V']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_BR_H'])) { + $brBR_H = $this->blk[$blvl]['border_radius_BR_H']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_BR_V'])) { + $brBR_V = $this->blk[$blvl]['border_radius_BR_V']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_BL_H'])) { + $brBL_H = $this->blk[$blvl]['border_radius_BL_H']; + $brset = true; + } + if (isset($this->blk[$blvl]['border_radius_BL_V'])) { + $brBL_V = $this->blk[$blvl]['border_radius_BL_V']; + $brset = true; + } + + if (!$this->blk[$blvl]['border_top'] || $divider == 'pagetop' || $continuingpage) { + $brTL_H = 0; + $brTL_V = 0; + $brTR_H = 0; + $brTR_V = 0; + } + if (!$this->blk[$blvl]['border_bottom'] || $blockstate == 1 || $divider == 'pagebottom') { + $brBL_H = 0; + $brBL_V = 0; + $brBR_H = 0; + $brBR_V = 0; + } + + // Disallow border-radius if it is smaller than the border width. + if ($brTL_H < min($border_left, $border_top)) { + $brTL_H = $brTL_V = 0; + } + if ($brTL_V < min($border_left, $border_top)) { + $brTL_V = $brTL_H = 0; + } + if ($brTR_H < min($border_right, $border_top)) { + $brTR_H = $brTR_V = 0; + } + if ($brTR_V < min($border_right, $border_top)) { + $brTR_V = $brTR_H = 0; + } + if ($brBL_H < min($border_left, $border_bottom)) { + $brBL_H = $brBL_V = 0; + } + if ($brBL_V < min($border_left, $border_bottom)) { + $brBL_V = $brBL_H = 0; + } + if ($brBR_H < min($border_right, $border_bottom)) { + $brBR_H = $brBR_V = 0; + } + if ($brBR_V < min($border_right, $border_bottom)) { + $brBR_V = $brBR_H = 0; + } + + // CHECK FOR radii that sum to > width or height of div ******** + $f = min($h / ($brTL_V + $brBL_V + 0.001), $h / ($brTR_V + $brBR_V + 0.001), $w / ($brTL_H + $brTR_H + 0.001), $w / ($brBL_H + $brBR_H + 0.001)); + if ($f < 1) { + $brTL_H *= $f; + $brTL_V *= $f; + $brTR_H *= $f; + $brTR_V *= $f; + $brBL_H *= $f; + $brBL_V *= $f; + $brBR_H *= $f; + $brBR_V *= $f; + } + /* -- END BORDER-RADIUS -- */ + + $tbcol = $this->colorConverter->convert(255, $this->PDFAXwarnings); + for ($l = 0; $l <= $blvl; $l++) { + if ($this->blk[$l]['bgcolor']) { + $tbcol = $this->blk[$l]['bgcolorarray']; + } + } + + // BORDERS + if (isset($this->blk[$blvl]['y0']) && $this->blk[$blvl]['y0']) { + $y0 = $this->blk[$blvl]['y0']; + } + $h = $y1 - $y0; + $w = $this->blk[$blvl]['width']; + + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $tbd = $this->blk[$blvl]['border_top']; + + $legend = ''; + $legbreakL = 0; + $legbreakR = 0; + // BORDER LEGEND + if (isset($this->blk[$blvl]['border_legend']) && $this->blk[$blvl]['border_legend']) { + $legend = $this->blk[$blvl]['border_legend']; // Same structure array as textbuffer + $txt = $legend[0] = ltrim($legend[0]); + if (!empty($legend[18])) { + $this->otl->trimOTLdata($legend[18], true, false); + } // *OTL* + // Set font, size, style, color + $this->SetFont($legend[4], $legend[2], $legend[11]); + if (isset($legend[3]) && $legend[3]) { + $cor = $legend[3]; + $this->SetTColor($cor); + } + $stringWidth = $this->GetStringWidth($txt, true, $legend[18], $legend[8]); + $save_x = $this->x; + $save_y = $this->y; + $save_currentfontfamily = $this->FontFamily; + $save_currentfontsize = $this->FontSizePt; + $save_currentfontstyle = $this->FontStyle; + $this->y = $y0 - $this->FontSize / 2 + $this->blk[$blvl]['border_top']['w'] / 2; + $this->x = $x0 + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_left']['w']; + + // Set the distance from the border line to the text ? make configurable variable + $gap = 0.2 * $this->FontSize; + $legbreakL = $this->x - $gap; + $legbreakR = $this->x + $stringWidth + $gap; + $this->magic_reverse_dir($txt, $this->blk[$blvl]['direction'], $legend[18]); + $fill = ''; + $this->Cell($stringWidth, $this->FontSize, $txt, '', 0, 'C', $fill, '', 0, 0, 0, 'M', $fill, false, $legend[18], $legend[8]); + // Reset + $this->x = $save_x; + $this->y = $save_y; + $this->SetFont($save_currentfontfamily, $save_currentfontstyle, $save_currentfontsize); + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + + if (isset($tbd['s']) && $tbd['s']) { + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('q'); + $this->SetLineWidth(0); + $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); + $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path + } + + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $legbreakL -= $border_top / 2; // because line cap different + $legbreakR += $border_top / 2; + $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'T'); + } /* -- BORDER-RADIUS -- */ elseif (($brTL_V && $brTL_H) || ($brTR_V && $brTR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $this->SetLineJoin(0); + $this->SetLineCap(0); + } + $s = ''; + if ($brTR_H && $brTR_V) { + $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_top / 2, $brTR_V - $border_top / 2, 1, 2, true)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + } + /* -- BORDER-RADIUS -- */ + if ($brTL_H && $brTL_V) { + if ($legend) { + if ($legbreakR < ($x0 + $w - $brTR_H)) { + $s .= (sprintf('%.3F %.3F l ', $legbreakR * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + if ($legbreakL > ($x0 + $brTL_H )) { + $s .= (sprintf('%.3F %.3F m ', $legbreakL * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + $s .= (sprintf('%.3F %.3F l ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE) . "\n"); + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $brTL_H ) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_top / 2, $brTL_V - $border_top / 2, 2, 1)) . "\n"; + } else { + /* -- END BORDER-RADIUS -- */ + if ($legend) { + if ($legbreakR < ($x0 + $w)) { + $s .= (sprintf('%.3F %.3F l ', $legbreakR * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + if ($legbreakL > ($x0)) { + $s .= (sprintf('%.3F %.3F m ', $legbreakL * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + } elseif ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $border_top / 2) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + } elseif ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_top / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_top / 2))) * Mpdf::SCALE)) . "\n"; + } + /* -- BORDER-RADIUS -- */ + } + /* -- END BORDER-RADIUS -- */ + $s .= 'S' . "\n"; + $this->writer->write($s); + + if ($tbd['style'] == 'double') { + $this->SetLineWidth($tbd['w'] / 3); + $this->SetDColor($tbcol); + $this->writer->write($s); + } + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('Q'); + } + + // Reset Corners and Dash off + $this->SetLineWidth(0.1); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + // Reinstate line above for dotted line divider when block border crosses a page + // elseif ($divider == 'pagetop' || $continuingpage) { + + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $tbd = $this->blk[$blvl]['border_bottom']; + if (isset($tbd['s']) && $tbd['s']) { + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('q'); + $this->SetLineWidth(0); + $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); + $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path + } + + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'B'); + } /* -- BORDER-RADIUS -- */ elseif (($brBL_V && $brBL_H) || ($brBR_V && $brBR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $this->SetLineJoin(0); + $this->SetLineCap(0); + } + $s = ''; + if ($brBL_H && $brBL_V) { + $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_bottom / 2, $brBL_V - $border_bottom / 2, 3, 2, true)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_bottom / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; + } + } + /* -- BORDER-RADIUS -- */ + if ($brBR_H && $brBR_V) { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_bottom / 2) - $brBR_H ) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; + $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_bottom / 2, $brBR_V - $border_bottom / 2, 4, 1)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_bottom / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_bottom / 2))) * Mpdf::SCALE)) . "\n"; + } + } + $s .= 'S' . "\n"; + $this->writer->write($s); + + if ($tbd['style'] == 'double') { + $this->SetLineWidth($tbd['w'] / 3); + $this->SetDColor($tbcol); + $this->writer->write($s); + } + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('Q'); + } + + // Reset Corners and Dash off + $this->SetLineWidth(0.1); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + // Reinstate line below for dotted line divider when block border crosses a page + // elseif ($blockstate == 1 || $divider == 'pagebottom') { + + if ($this->blk[$blvl]['border_left']) { + $tbd = $this->blk[$blvl]['border_left']; + if (isset($tbd['s']) && $tbd['s']) { + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('q'); + $this->SetLineWidth(0); + $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); + $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path + } + + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'L'); + } /* -- BORDER-RADIUS -- */ elseif (($brTL_V && $brTL_H) || ($brBL_V && $brBL_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $this->SetLineJoin(0); + $this->SetLineCap(0); + } + $s = ''; + if ($brTL_V && $brTL_H) { + $s .= ($this->_EllipseArc($x0 + $brTL_H, $y0 + $brTL_V, $brTL_H - $border_left / 2, $brTL_V - $border_left / 2, 2, 2, true)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_left / 2))) * Mpdf::SCALE)) . "\n"; + } + } + /* -- BORDER-RADIUS -- */ + if ($brBL_V && $brBL_H) { + $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_left / 2) - $brBL_V) ) * Mpdf::SCALE)) . "\n"; + $s .= ($this->_EllipseArc($x0 + $brBL_H, $y0 + $h - $brBL_V, $brBL_H - $border_left / 2, $brBL_V - $border_left / 2, 3, 1)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h) ) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + ($border_left / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_left / 2)) ) * Mpdf::SCALE)) . "\n"; + } + } + $s .= 'S' . "\n"; + $this->writer->write($s); + + if ($tbd['style'] == 'double') { + $this->SetLineWidth($tbd['w'] / 3); + $this->SetDColor($tbcol); + $this->writer->write($s); + } + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('Q'); + } + + // Reset Corners and Dash off + $this->SetLineWidth(0.1); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($this->blk[$blvl]['border_right']) { + $tbd = $this->blk[$blvl]['border_right']; + if (isset($tbd['s']) && $tbd['s']) { + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('q'); + $this->SetLineWidth(0); + $this->writer->write(sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)); + $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path + } + + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], $divider, $continuingpage, 'R'); + } /* -- BORDER-RADIUS -- */ elseif (($brTR_V && $brTR_H) || ($brBR_V && $brBR_H) || $tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $this->SetLineJoin(0); + $this->SetLineCap(0); + } + $s = ''; + if ($brBR_V && $brBR_H) { + $s .= ($this->_EllipseArc($x0 + $w - $brBR_H, $y0 + $h - $brBR_V, $brBR_H - $border_right / 2, $brBR_V - $border_right / 2, 4, 2, true)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F m ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + $h - ($border_right / 2))) * Mpdf::SCALE)) . "\n"; + } + } + /* -- BORDER-RADIUS -- */ + if ($brTR_V && $brTR_H) { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_right / 2) + $brTR_V) ) * Mpdf::SCALE)) . "\n"; + $s .= ($this->_EllipseArc($x0 + $w - $brTR_H, $y0 + $brTR_V, $brTR_H - $border_right / 2, $brTR_V - $border_right / 2, 1, 1)) . "\n"; + } else { /* -- END BORDER-RADIUS -- */ + if ($tbd['style'] == 'solid' || $tbd['style'] == 'double') { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0) ) * Mpdf::SCALE)) . "\n"; + } else { + $s .= (sprintf('%.3F %.3F l ', ($x0 + $w - ($border_right / 2)) * Mpdf::SCALE, ($this->h - ($y0 + ($border_right / 2)) ) * Mpdf::SCALE)) . "\n"; + } + } + $s .= 'S' . "\n"; + $this->writer->write($s); + + if ($tbd['style'] == 'double') { + $this->SetLineWidth($tbd['w'] / 3); + $this->SetDColor($tbcol); + $this->writer->write($s); + } + if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') { + $this->writer->write('Q'); + } + + // Reset Corners and Dash off + $this->SetLineWidth(0.1); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + + + $this->SetDash(); + $this->y = $save_y; + + + // BACKGROUNDS are disabled in columns/kbt/headers - messes up the repositioning in printcolumnbuffer + if ($this->ColActive || $this->kwt || $this->keep_block_together) { + return; + } + + + $bgx0 = $x0; + $bgx1 = $x1; + $bgy0 = $y0; + $bgy1 = $y1; + + // Defined br values represent the radius of the outer curve - need to take border-width/2 from each radius for drawing the borders + if (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'padding-box') { + $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w']); + $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w']); + $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w']); + $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w']); + $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w']); + $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w']); + $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w']); + $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w']); + $bgx0 += $this->blk[$blvl]['border_left']['w']; + $bgx1 -= $this->blk[$blvl]['border_right']['w']; + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $bgy0 += $this->blk[$blvl]['border_top']['w']; + } + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $bgy1 -= $this->blk[$blvl]['border_bottom']['w']; + } + } elseif (isset($this->blk[$blvl]['background_clip']) && $this->blk[$blvl]['background_clip'] == 'content-box') { + $brbgTL_H = max(0, $brTL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']); + $brbgTL_V = max(0, $brTL_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']); + $brbgTR_H = max(0, $brTR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']); + $brbgTR_V = max(0, $brTR_V - $this->blk[$blvl]['border_top']['w'] - $this->blk[$blvl]['padding_top']); + $brbgBL_H = max(0, $brBL_H - $this->blk[$blvl]['border_left']['w'] - $this->blk[$blvl]['padding_left']); + $brbgBL_V = max(0, $brBL_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']); + $brbgBR_H = max(0, $brBR_H - $this->blk[$blvl]['border_right']['w'] - $this->blk[$blvl]['padding_right']); + $brbgBR_V = max(0, $brBR_V - $this->blk[$blvl]['border_bottom']['w'] - $this->blk[$blvl]['padding_bottom']); + $bgx0 += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; + $bgx1 -= $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']; + if (($this->blk[$blvl]['border_top']['w'] || $this->blk[$blvl]['padding_top']) && $divider != 'pagetop' && !$continuingpage) { + $bgy0 += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; + } + if (($this->blk[$blvl]['border_bottom']['w'] || $this->blk[$blvl]['padding_bottom']) && $blockstate != 1 && $divider != 'pagebottom') { + $bgy1 -= $this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']; + } + } else { + $brbgTL_H = $brTL_H; + $brbgTL_V = $brTL_V; + $brbgTR_H = $brTR_H; + $brbgTR_V = $brTR_V; + $brbgBL_H = $brBL_H; + $brbgBL_V = $brBL_V; + $brbgBR_H = $brBR_H; + $brbgBR_V = $brBR_V; + } + + // Set clipping path + $s = ' q 0 w '; // Line width=0 + $s .= sprintf('%.3F %.3F m ', ($bgx0 + $brbgTL_H ) * Mpdf::SCALE, ($this->h - $bgy0) * Mpdf::SCALE); // start point TL before the arc + /* -- BORDER-RADIUS -- */ + if ($brbgTL_H || $brbgTL_V) { + $s .= $this->_EllipseArc($bgx0 + $brbgTL_H, $bgy0 + $brbgTL_V, $brbgTL_H, $brbgTL_V, 2); // segment 2 TL + } + /* -- END BORDER-RADIUS -- */ + $s .= sprintf('%.3F %.3F l ', ($bgx0) * Mpdf::SCALE, ($this->h - ($bgy1 - $brbgBL_V )) * Mpdf::SCALE); // line to BL + /* -- BORDER-RADIUS -- */ + if ($brbgBL_H || $brbgBL_V) { + $s .= $this->_EllipseArc($bgx0 + $brbgBL_H, $bgy1 - $brbgBL_V, $brbgBL_H, $brbgBL_V, 3); // segment 3 BL + } + /* -- END BORDER-RADIUS -- */ + $s .= sprintf('%.3F %.3F l ', ($bgx1 - $brbgBR_H ) * Mpdf::SCALE, ($this->h - ($bgy1)) * Mpdf::SCALE); // line to BR + /* -- BORDER-RADIUS -- */ + if ($brbgBR_H || $brbgBR_V) { + $s .= $this->_EllipseArc($bgx1 - $brbgBR_H, $bgy1 - $brbgBR_V, $brbgBR_H, $brbgBR_V, 4); // segment 4 BR + } + /* -- END BORDER-RADIUS -- */ + $s .= sprintf('%.3F %.3F l ', ($bgx1) * Mpdf::SCALE, ($this->h - ($bgy0 + $brbgTR_V)) * Mpdf::SCALE); // line to TR + /* -- BORDER-RADIUS -- */ + if ($brbgTR_H || $brbgTR_V) { + $s .= $this->_EllipseArc($bgx1 - $brbgTR_H, $bgy0 + $brbgTR_V, $brbgTR_H, $brbgTR_V, 1); // segment 1 TR + } + /* -- END BORDER-RADIUS -- */ + $s .= sprintf('%.3F %.3F l ', ($bgx0 + $brbgTL_H ) * Mpdf::SCALE, ($this->h - $bgy0) * Mpdf::SCALE); // line to TL + // Box Shadow + $shadow = ''; + if (isset($this->blk[$blvl]['box_shadow']) && $this->blk[$blvl]['box_shadow'] && $h > 0) { + foreach ($this->blk[$blvl]['box_shadow'] as $sh) { + // Colors + if ($sh['col'][0] == 1) { + $colspace = 'Gray'; + if ($sh['col'][2] == 1) { + $col1 = '1' . $sh['col'][1] . '1' . $sh['col'][3]; + } else { + $col1 = '1' . $sh['col'][1] . '1' . chr(100); + } + $col2 = '1' . $sh['col'][1] . '1' . chr(0); + } elseif ($sh['col'][0] == 4) { // CMYK + $colspace = 'CMYK'; + $col1 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(100); + $col2 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(0); + } elseif ($sh['col'][0] == 5) { // RGBa + $colspace = 'RGB'; + $col1 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4]; + $col2 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(0); + } elseif ($sh['col'][0] == 6) { // CMYKa + $colspace = 'CMYK'; + $col1 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . $sh['col'][5]; + $col2 = '6' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . $sh['col'][4] . chr(0); + } else { + $colspace = 'RGB'; + $col1 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(100); + $col2 = '5' . $sh['col'][1] . $sh['col'][2] . $sh['col'][3] . chr(0); + } + + // Use clipping path as set above (and rectangle around page) to clip area outside box + $shadow .= $s; // Use the clipping path with W* + $shadow .= sprintf('0 %.3F m %.3F %.3F l ', $this->h * Mpdf::SCALE, $this->w * Mpdf::SCALE, $this->h * Mpdf::SCALE); + $shadow .= sprintf('%.3F 0 l 0 0 l 0 %.3F l ', $this->w * Mpdf::SCALE, $this->h * Mpdf::SCALE); + $shadow .= 'W n' . "\n"; + + $sh['blur'] = abs($sh['blur']); // cannot have negative blur value + // Ensure spread/blur do not make effective shadow width/height < 0 + // Could do more complex things but this just adjusts spread value + if (-$sh['spread'] + $sh['blur'] / 2 > min($w / 2, $h / 2)) { + $sh['spread'] = $sh['blur'] / 2 - min($w / 2, $h / 2) + 0.01; + } + // Shadow Offset + if ($sh['x'] || $sh['y']) { + $shadow .= sprintf(' q 1 0 0 1 %.4F %.4F cm', $sh['x'] * Mpdf::SCALE, -$sh['y'] * Mpdf::SCALE) . "\n"; + } + + // Set path for INNER shadow + $shadow .= ' q 0 w '; + $shadow .= $this->SetFColor($col1, true) . "\n"; + if ($col1[0] == 5 && ord($col1[4]) < 100) { // RGBa + $shadow .= $this->SetAlpha(ord($col1[4]) / 100, 'Normal', true, 'F') . "\n"; + } elseif ($col1[0] == 6 && ord($col1[5]) < 100) { // CMYKa + $shadow .= $this->SetAlpha(ord($col1[5]) / 100, 'Normal', true, 'F') . "\n"; + } elseif ($col1[0] == 1 && $col1[2] == 1 && ord($col1[3]) < 100) { // Gray + $shadow .= $this->SetAlpha(ord($col1[3]) / 100, 'Normal', true, 'F') . "\n"; + } + + // Blur edges + $mag = 0.551784; // Bezier Control magic number for 4-part spline for circle/ellipse + $mag2 = 0.551784; // Bezier Control magic number to fill in edge of blurred rectangle + $d1 = $sh['spread'] + $sh['blur'] / 2; + $d2 = $sh['spread'] - $sh['blur'] / 2; + $bl = $sh['blur']; + $x00 = $x0 - $d1; + $y00 = $y0 - $d1; + $w00 = $w + $d1 * 2; + $h00 = $h + $d1 * 2; + + // If any border-radius is greater width-negative spread(inner edge), ignore radii for shadow or screws up + $flatten = false; + if (max($brbgTR_H, $brbgTL_H, $brbgBR_H, $brbgBL_H) >= $w + $d2) { + $flatten = true; + } + if (max($brbgTR_V, $brbgTL_V, $brbgBR_V, $brbgBL_V) >= $h + $d2) { + $flatten = true; + } + + + // TOP RIGHT corner + $p1x = $x00 + $w00 - $d1 - $brbgTR_H; + $p1c2x = $p1x + ($d2 + $brbgTR_H) * $mag; + $p1y = $y00 + $bl; + $p2x = $x00 + $w00 - $d1 - $brbgTR_H; + $p2c2x = $p2x + ($d1 + $brbgTR_H) * $mag; + $p2y = $y00; + $p2c1y = $p2y + $bl / 2; + $p3x = $x00 + $w00; + $p3c2x = $p3x - $bl / 2; + $p3y = $y00 + $d1 + $brbgTR_V; + $p3c1y = $p3y - ($d1 + $brbgTR_V) * $mag; + $p4x = $x00 + $w00 - $bl; + $p4y = $y00 + $d1 + $brbgTR_V; + $p4c2y = $p4y - ($d2 + $brbgTR_V) * $mag; + if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { + $p1x = $x00 + $w00 - $bl; + $p1c2x = $p1x; + $p2x = $x00 + $w00 - $bl; + $p2c2x = $p2x + $bl * $mag2; + $p3y = $y00 + $bl; + $p3c1y = $p3y - $bl * $mag2; + $p4y = $y00 + $bl; + $p4c2y = $p4y; + } + + $shadow .= sprintf('%.3F %.3F m ', ($p1x ) * Mpdf::SCALE, ($this->h - ($p1y )) * Mpdf::SCALE); + $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x) * Mpdf::SCALE, ($this->h - ($p1y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4c2y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); + $patch_array[0]['f'] = 0; + $patch_array[0]['points'] = [$p1x, $p1y, $p1x, $p1y, + $p2x, $p2c1y, $p2x, $p2y, $p2c2x, $p2y, + $p3x, $p3c1y, $p3x, $p3y, $p3c2x, $p3y, + $p4x, $p4y, $p4x, $p4y, $p4x, $p4c2y, + $p1c2x, $p1y]; + $patch_array[0]['colors'] = [$col1, $col2, $col2, $col1]; + + + // RIGHT + $p1x = $x00 + $w00; // control point only matches p3 preceding + $p1y = $y00 + $d1 + $brbgTR_V; + $p2x = $x00 + $w00 - $bl; // control point only matches p4 preceding + $p2y = $y00 + $d1 + $brbgTR_V; + $p3x = $x00 + $w00 - $bl; + $p3y = $y00 + $h00 - $d1 - $brbgBR_V; + $p4x = $x00 + $w00; + $p4c1x = $p4x - $bl / 2; + $p4y = $y00 + $h00 - $d1 - $brbgBR_V; + if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { + $p1y = $y00 + $bl; + $p2y = $y00 + $bl; + } + if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { + $p3y = $y00 + $h00 - $bl; + $p4y = $y00 + $h00 - $bl; + } + + $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); + $patch_array[1]['f'] = 2; + $patch_array[1]['points'] = [$p2x, $p2y, + $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, + $p4c1x, $p4y, $p4x, $p4y, $p4x, $p4y, + $p1x, $p1y]; + $patch_array[1]['colors'] = [$col1, $col2]; + + + // BOTTOM RIGHT corner + $p1x = $x00 + $w00 - $bl; // control points only matches p3 preceding + $p1y = $y00 + $h00 - $d1 - $brbgBR_V; + $p1c2y = $p1y + ($d2 + $brbgBR_V) * $mag; + $p2x = $x00 + $w00; // control point only matches p4 preceding + $p2y = $y00 + $h00 - $d1 - $brbgBR_V; + $p2c2y = $p2y + ($d1 + $brbgBR_V) * $mag; + $p3x = $x00 + $w00 - $d1 - $brbgBR_H; + $p3c1x = $p3x + ($d1 + $brbgBR_H) * $mag; + $p3y = $y00 + $h00; + $p3c2y = $p3y - $bl / 2; + $p4x = $x00 + $w00 - $d1 - $brbgBR_H; + $p4c2x = $p4x + ($d2 + $brbgBR_H) * $mag; + $p4y = $y00 + $h00 - $bl; + + if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { + $p1y = $y00 + $h00 - $bl; + $p1c2y = $p1y; + $p2y = $y00 + $h00 - $bl; + $p2c2y = $p2y + $bl * $mag2; + $p3x = $x00 + $w00 - $bl; + $p3c1x = $p3x + $bl * $mag2; + $p4x = $x00 + $w00 - $bl; + $p4c2x = $p4x; + } + + $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x) * Mpdf::SCALE, ($this->h - ($p1c2y)) * Mpdf::SCALE, ($p4c2x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); + $patch_array[2]['f'] = 2; + $patch_array[2]['points'] = [$p2x, $p2c2y, + $p3c1x, $p3y, $p3x, $p3y, $p3x, $p3c2y, + $p4x, $p4y, $p4x, $p4y, $p4c2x, $p4y, + $p1x, $p1c2y]; + $patch_array[2]['colors'] = [$col2, $col1]; + + + + // BOTTOM + $p1x = $x00 + $w00 - $d1 - $brbgBR_H; // control point only matches p3 preceding + $p1y = $y00 + $h00; + $p2x = $x00 + $w00 - $d1 - $brbgBR_H; // control point only matches p4 preceding + $p2y = $y00 + $h00 - $bl; + $p3x = $x00 + $d1 + $brbgBL_H; + $p3y = $y00 + $h00 - $bl; + $p4x = $x00 + $d1 + $brbgBL_H; + $p4y = $y00 + $h00; + $p4c1y = $p4y - $bl / 2; + + if (-$d2 > min($brbgBR_H, $brbgBR_V) || $flatten) { + $p1x = $x00 + $w00 - $bl; + $p2x = $x00 + $w00 - $bl; + } + if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { + $p3x = $x00 + $bl; + $p4x = $x00 + $bl; + } + + $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); + $patch_array[3]['f'] = 2; + $patch_array[3]['points'] = [$p2x, $p2y, + $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, + $p4x, $p4c1y, $p4x, $p4y, $p4x, $p4y, + $p1x, $p1y]; + $patch_array[3]['colors'] = [$col1, $col2]; + + // BOTTOM LEFT corner + $p1x = $x00 + $d1 + $brbgBL_H; + $p1c2x = $p1x - ($d2 + $brbgBL_H) * $mag; // control points only matches p3 preceding + $p1y = $y00 + $h00 - $bl; + $p2x = $x00 + $d1 + $brbgBL_H; + $p2c2x = $p2x - ($d1 + $brbgBL_H) * $mag; // control point only matches p4 preceding + $p2y = $y00 + $h00; + $p3x = $x00; + $p3c2x = $p3x + $bl / 2; + $p3y = $y00 + $h00 - $d1 - $brbgBL_V; + $p3c1y = $p3y + ($d1 + $brbgBL_V) * $mag; + $p4x = $x00 + $bl; + $p4y = $y00 + $h00 - $d1 - $brbgBL_V; + $p4c2y = $p4y + ($d2 + $brbgBL_V) * $mag; + if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { + $p1x = $x00 + $bl; + $p1c2x = $p1x; + $p2x = $x00 + $bl; + $p2c2x = $p2x - $bl * $mag2; + $p3y = $y00 + $h00 - $bl; + $p3c1y = $p3y + $bl * $mag2; + $p4y = $y00 + $h00 - $bl; + $p4c2y = $p4y; + } + + $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1c2x) * Mpdf::SCALE, ($this->h - ($p1y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4c2y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); + $patch_array[4]['f'] = 2; + $patch_array[4]['points'] = [$p2c2x, $p2y, + $p3x, $p3c1y, $p3x, $p3y, $p3c2x, $p3y, + $p4x, $p4y, $p4x, $p4y, $p4x, $p4c2y, + $p1c2x, $p1y]; + $patch_array[4]['colors'] = [$col2, $col1]; + + + // LEFT - joins on the right (C3-C4 of previous): f = 2 + $p1x = $x00; // control point only matches p3 preceding + $p1y = $y00 + $h00 - $d1 - $brbgBL_V; + $p2x = $x00 + $bl; // control point only matches p4 preceding + $p2y = $y00 + $h00 - $d1 - $brbgBL_V; + $p3x = $x00 + $bl; + $p3y = $y00 + $d1 + $brbgTL_V; + $p4x = $x00; + $p4c1x = $p4x + $bl / 2; + $p4y = $y00 + $d1 + $brbgTL_V; + if (-$d2 > min($brbgBL_H, $brbgBL_V) || $flatten) { + $p1y = $y00 + $h00 - $bl; + $p2y = $y00 + $h00 - $bl; + } + if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { + $p3y = $y00 + $bl; + $p4y = $y00 + $bl; + } + + $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); + $patch_array[5]['f'] = 2; + $patch_array[5]['points'] = [$p2x, $p2y, + $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, + $p4c1x, $p4y, $p4x, $p4y, $p4x, $p4y, + $p1x, $p1y]; + $patch_array[5]['colors'] = [$col1, $col2]; + + // TOP LEFT corner + $p1x = $x00 + $bl; // control points only matches p3 preceding + $p1y = $y00 + $d1 + $brbgTL_V; + $p1c2y = $p1y - ($d2 + $brbgTL_V) * $mag; + $p2x = $x00; // control point only matches p4 preceding + $p2y = $y00 + $d1 + $brbgTL_V; + $p2c2y = $p2y - ($d1 + $brbgTL_V) * $mag; + $p3x = $x00 + $d1 + $brbgTL_H; + $p3c1x = $p3x - ($d1 + $brbgTL_H) * $mag; + $p3y = $y00; + $p3c2y = $p3y + $bl / 2; + $p4x = $x00 + $d1 + $brbgTL_H; + $p4c2x = $p4x - ($d2 + $brbgTL_H) * $mag; + $p4y = $y00 + $bl; + + if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { + $p1y = $y00 + $bl; + $p1c2y = $p1y; + $p2y = $y00 + $bl; + $p2c2y = $p2y - $bl * $mag2; + $p3x = $x00 + $bl; + $p3c1x = $p3x - $bl * $mag2; + $p4x = $x00 + $bl; + $p4c2x = $p4x; + } + + $shadow .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($p1x) * Mpdf::SCALE, ($this->h - ($p1c2y)) * Mpdf::SCALE, ($p4c2x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE, ($p4x) * Mpdf::SCALE, ($this->h - ($p4y)) * Mpdf::SCALE); + $patch_array[6]['f'] = 2; + $patch_array[6]['points'] = [$p2x, $p2c2y, + $p3c1x, $p3y, $p3x, $p3y, $p3x, $p3c2y, + $p4x, $p4y, $p4x, $p4y, $p4c2x, $p4y, + $p1x, $p1c2y]; + $patch_array[6]['colors'] = [$col2, $col1]; + + + // TOP - joins on the right (C3-C4 of previous): f = 2 + $p1x = $x00 + $d1 + $brbgTL_H; // control point only matches p3 preceding + $p1y = $y00; + $p2x = $x00 + $d1 + $brbgTL_H; // control point only matches p4 preceding + $p2y = $y00 + $bl; + $p3x = $x00 + $w00 - $d1 - $brbgTR_H; + $p3y = $y00 + $bl; + $p4x = $x00 + $w00 - $d1 - $brbgTR_H; + $p4y = $y00; + $p4c1y = $p4y + $bl / 2; + if (-$d2 > min($brbgTL_H, $brbgTL_V) || $flatten) { + $p1x = $x00 + $bl; + $p2x = $x00 + $bl; + } + if (-$d2 > min($brbgTR_H, $brbgTR_V) || $flatten) { + $p3x = $x00 + $w00 - $bl; + $p4x = $x00 + $w00 - $bl; + } + + $shadow .= sprintf('%.3F %.3F l ', ($p3x ) * Mpdf::SCALE, ($this->h - ($p3y )) * Mpdf::SCALE); + $patch_array[7]['f'] = 2; + $patch_array[7]['points'] = [$p2x, $p2y, + $p3x, $p3y, $p3x, $p3y, $p3x, $p3y, + $p4x, $p4c1y, $p4x, $p4y, $p4x, $p4y, + $p1x, $p1y]; + $patch_array[7]['colors'] = [$col1, $col2]; + + $shadow .= ' h f Q ' . "\n"; // Close path and Fill the inner solid shadow + + if ($bl) { + $shadow .= $this->gradient->CoonsPatchMesh($x00, $y00, $w00, $h00, $patch_array, $x00, $x00 + $w00, $y00, $y00 + $h00, $colspace, true); + } + + if ($sh['x'] || $sh['y']) { + $shadow .= ' Q' . "\n"; // Shadow Offset + } + $shadow .= ' Q' . "\n"; // Ends path no-op & Sets the clipping path + } + } + + $s .= ' W n '; // Ends path no-op & Sets the clipping path + + if ($this->blk[$blvl]['bgcolor']) { + $this->pageBackgrounds[$blvl][] = [ + 'x' => $x0, + 'y' => $y0, + 'w' => $w, + 'h' => $h, + 'col' => $this->blk[$blvl]['bgcolorarray'], + 'clippath' => $s, + 'visibility' => $this->visibility, + 'shadow' => $shadow, + 'z-index' => $this->current_layer, + ]; + } elseif ($shadow) { + $this->pageBackgrounds[$blvl][] = [ + 'x' => 0, + 'y' => 0, + 'w' => 0, + 'h' => 0, + 'shadowonly' => true, + 'col' => '', + 'clippath' => '', + 'visibility' => $this->visibility, + 'shadow' => $shadow, + 'z-index' => $this->current_layer, + ]; + } + + /* -- BACKGROUNDS -- */ + if (isset($this->blk[$blvl]['gradient'])) { + $g = $this->gradient->parseBackgroundGradient($this->blk[$blvl]['gradient']); + if ($g) { + $gx = $x0; + $gy = $y0; + $this->pageBackgrounds[$blvl][] = [ + 'gradient' => true, + 'x' => $gx, + 'y' => $gy, + 'w' => $w, + 'h' => $h, + 'gradtype' => $g['type'], + 'stops' => $g['stops'], + 'colorspace' => $g['colorspace'], + 'coords' => $g['coords'], + 'extend' => $g['extend'], + 'clippath' => $s, + 'visibility' => $this->visibility, + 'z-index' => $this->current_layer + ]; + } + } + + if (isset($this->blk[$blvl]['background-image'])) { + if (isset($this->blk[$blvl]['background-image']['gradient']) && $this->blk[$blvl]['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $this->blk[$blvl]['background-image']['gradient'])) { + $g = $this->gradient->parseMozGradient($this->blk[$blvl]['background-image']['gradient']); + if ($g) { + $gx = $x0; + $gy = $y0; + // origin specifies the background-positioning-area (bpa) + if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') { + $gx += $this->blk[$blvl]['border_left']['w']; + $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']); + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $gy += $this->blk[$blvl]['border_top']['w']; + } + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $gy1 = $y1 - $this->blk[$blvl]['border_bottom']['w']; + } else { + $gy1 = $y1; + } + $h = $gy1 - $gy; + } elseif ($this->blk[$blvl]['background-image']['origin'] == 'content-box') { + $gx += $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; + $w -= ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']); + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $gy += $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; + } + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $gy1 = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']); + } else { + $gy1 = $y1 - $this->blk[$blvl]['padding_bottom']; + } + $h = $gy1 - $gy; + } + + if (isset($this->blk[$blvl]['background-image']['size']['w']) && $this->blk[$blvl]['background-image']['size']['w']) { + $size = $this->blk[$blvl]['background-image']['size']; + if ($size['w'] != 'contain' && $size['w'] != 'cover') { + if (stristr($size['w'], '%')) { + $size['w'] = (float) $size['w']; + $size['w'] /= 100; + $w *= $size['w']; + } elseif ($size['w'] != 'auto') { + $w = $size['w']; + } + if (stristr($size['h'], '%')) { + $size['h'] = (float) $size['h']; + $size['h'] /= 100; + $h *= $size['h']; + } elseif ($size['h'] != 'auto') { + $h = $size['h']; + } + } + } + $this->pageBackgrounds[$blvl][] = [ + 'gradient' => true, + 'x' => $gx, + 'y' => $gy, + 'w' => $w, + 'h' => $h, + 'gradtype' => $g['type'], + 'stops' => $g['stops'], + 'colorspace' => $g['colorspace'], + 'coords' => $g['coords'], + 'extend' => $g['extend'], + 'clippath' => $s, + 'visibility' => $this->visibility, + 'z-index' => $this->current_layer + ]; + } + + } else { + + $image_id = $this->blk[$blvl]['background-image']['image_id']; + $orig_w = $this->blk[$blvl]['background-image']['orig_w']; + $orig_h = $this->blk[$blvl]['background-image']['orig_h']; + $x_pos = $this->blk[$blvl]['background-image']['x_pos']; + $y_pos = $this->blk[$blvl]['background-image']['y_pos']; + $x_repeat = $this->blk[$blvl]['background-image']['x_repeat']; + $y_repeat = $this->blk[$blvl]['background-image']['y_repeat']; + $resize = $this->blk[$blvl]['background-image']['resize']; + $opacity = $this->blk[$blvl]['background-image']['opacity']; + $itype = $this->blk[$blvl]['background-image']['itype']; + $size = $this->blk[$blvl]['background-image']['size']; + // origin specifies the background-positioning-area (bpa) + + $bpa = ['x' => $x0, 'y' => $y0, 'w' => $w, 'h' => $h]; + + if ($this->blk[$blvl]['background-image']['origin'] == 'padding-box') { + + $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w']; + $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['border_right']['w']); + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w']; + } else { + $bpa['y'] = $y0; + } + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $bpay = $y1 - $this->blk[$blvl]['border_bottom']['w']; + } else { + $bpay = $y1; + } + $bpa['h'] = $bpay - $bpa['y']; + + } elseif ($this->blk[$blvl]['background-image']['origin'] == 'content-box') { + + $bpa['x'] = $x0 + $this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left']; + $bpa['w'] = $w - ($this->blk[$blvl]['border_left']['w'] + $this->blk[$blvl]['padding_left'] + $this->blk[$blvl]['border_right']['w'] + $this->blk[$blvl]['padding_right']); + if ($this->blk[$blvl]['border_top'] && $divider != 'pagetop' && !$continuingpage) { + $bpa['y'] = $y0 + $this->blk[$blvl]['border_top']['w'] + $this->blk[$blvl]['padding_top']; + } else { + $bpa['y'] = $y0 + $this->blk[$blvl]['padding_top']; + } + if ($this->blk[$blvl]['border_bottom'] && $blockstate != 1 && $divider != 'pagebottom') { + $bpay = $y1 - ($this->blk[$blvl]['border_bottom']['w'] + $this->blk[$blvl]['padding_bottom']); + } else { + $bpay = $y1 - $this->blk[$blvl]['padding_bottom']; + } + $bpa['h'] = $bpay - $bpa['y']; + + } + + $this->pageBackgrounds[$blvl][] = [ + 'x' => $x0, + 'y' => $y0, + 'w' => $w, + 'h' => $h, + 'image_id' => $image_id, + 'orig_w' => $orig_w, + 'orig_h' => $orig_h, + 'x_pos' => $x_pos, + 'y_pos' => $y_pos, + 'x_repeat' => $x_repeat, + 'y_repeat' => $y_repeat, + 'clippath' => $s, + 'resize' => $resize, + 'opacity' => $opacity, + 'itype' => $itype, + 'visibility' => $this->visibility, + 'z-index' => $this->current_layer, + 'size' => $size, + 'bpa' => $bpa + ]; + } + } + /* -- END BACKGROUNDS -- */ + + // Float DIV + $this->blk[$blvl]['bb_painted'][$this->page] = true; + } + /* -- BORDER-RADIUS -- */ + + function _EllipseArc($x0, $y0, $rx, $ry, $seg = 1, $part = false, $start = false) + { + // Anticlockwise segment 1-4 TR-TL-BL-BR (part=1 or 2) + $s = ''; + + if ($rx < 0) { + $rx = 0; + } + + if ($ry < 0) { + $ry = 0; + } + + $rx *= Mpdf::SCALE; + $ry *= Mpdf::SCALE; + + $astart = 0; + + if ($seg == 1) { // Top Right + $afinish = 90; + $nSeg = 4; + } elseif ($seg == 2) { // Top Left + $afinish = 180; + $nSeg = 8; + } elseif ($seg == 3) { // Bottom Left + $afinish = 270; + $nSeg = 12; + } else { // Bottom Right + $afinish = 360; + $nSeg = 16; + } + + $astart = deg2rad((float) $astart); + $afinish = deg2rad((float) $afinish); + + $totalAngle = $afinish - $astart; + $dt = $totalAngle / $nSeg; // segment angle + $dtm = $dt / 3; + $x0 *= Mpdf::SCALE; + $y0 = ($this->h - $y0) * Mpdf::SCALE; + $t1 = $astart; + $a0 = $x0 + ($rx * cos($t1)); + $b0 = $y0 + ($ry * sin($t1)); + $c0 = -$rx * sin($t1); + $d0 = $ry * cos($t1); + $op = false; + + for ($i = 1; $i <= $nSeg; $i++) { + // Draw this bit of the total curve + $t1 = ($i * $dt) + $astart; + $a1 = $x0 + ($rx * cos($t1)); + $b1 = $y0 + ($ry * sin($t1)); + $c1 = -$rx * sin($t1); + $d1 = $ry * cos($t1); + if ($i > ($nSeg - 4) && (!$part || ($part == 1 && $i <= $nSeg - 2) || ($part == 2 && $i > $nSeg - 2))) { + if ($start && !$op) { + $s .= sprintf('%.3F %.3F m ', $a0, $b0); + } + $s .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($a0 + ($c0 * $dtm)), ($b0 + ($d0 * $dtm)), ($a1 - ($c1 * $dtm)), ($b1 - ($d1 * $dtm)), $a1, $b1); + $op = true; + } + $a0 = $a1; + $b0 = $b1; + $c0 = $c1; + $d0 = $d1; + } + + return $s; + } + + /* -- END BORDER-RADIUS -- */ + + function PaintDivLnBorder($state = 0, $blvl = 0, $h = 0) + { + // $state = 0 normal; 1 top; 2 bottom; 3 top and bottom + $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y + $h; + + $save_y = $this->y; + + $w = $this->blk[$blvl]['width']; + $x0 = $this->x; // left + $y0 = $this->y; // top + $x1 = $this->x + $w; // bottom + $y1 = $this->y + $h; // bottom + $continuingpage = (isset($this->blk[$blvl]['startpage']) && $this->blk[$blvl]['startpage'] != $this->page); + + if ($this->blk[$blvl]['border_top'] && ($state == 1 || $state == 3)) { + $tbd = $this->blk[$blvl]['border_top']; + if (isset($tbd['s']) && $tbd['s']) { + $this->_setBorderLine($tbd); + $this->y = $y0 + ($tbd['w'] / 2); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', $continuingpage, 'T'); + $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $this->y); + } else { + $this->SetLineJoin(0); + $this->SetLineCap(0); + $this->Line($x0, $this->y, $x0 + $w, $this->y); + } + $this->y += $tbd['w']; + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($this->blk[$blvl]['border_left']) { + $tbd = $this->blk[$blvl]['border_left']; + if (isset($tbd['s']) && $tbd['s']) { + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->y = $y0 + ($tbd['w'] / 2); + $this->_setDashBorder($tbd['style'], '', $continuingpage, 'L'); + $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + ($tbd['w'] / 2), $y0 + $h - ($tbd['w'] / 2)); + } else { + $this->y = $y0; + $this->SetLineJoin(0); + $this->SetLineCap(0); + $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + ($tbd['w'] / 2), $y0 + $h); + } + $this->y += $tbd['w']; + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($this->blk[$blvl]['border_right']) { + $tbd = $this->blk[$blvl]['border_right']; + if (isset($tbd['s']) && $tbd['s']) { + $this->_setBorderLine($tbd); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->y = $y0 + ($tbd['w'] / 2); + $this->_setDashBorder($tbd['style'], '', $continuingpage, 'R'); + $this->Line($x0 + $w - ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $y0 + $h - ($tbd['w'] / 2)); + } else { + $this->y = $y0; + $this->SetLineJoin(0); + $this->SetLineCap(0); + $this->Line($x0 + $w - ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $y0 + $h); + } + $this->y += $tbd['w']; + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($this->blk[$blvl]['border_bottom'] && $state > 1) { + $tbd = $this->blk[$blvl]['border_bottom']; + if (isset($tbd['s']) && $tbd['s']) { + $this->_setBorderLine($tbd); + $this->y = $y0 + $h - ($tbd['w'] / 2); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', $continuingpage, 'B'); + $this->Line($x0 + ($tbd['w'] / 2), $this->y, $x0 + $w - ($tbd['w'] / 2), $this->y); + } else { + $this->SetLineJoin(0); + $this->SetLineCap(0); + $this->Line($x0, $this->y, $x0 + $w, $this->y); + } + $this->y += $tbd['w']; + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + $this->SetDash(); + $this->y = $save_y; + } + + function PaintImgBorder($objattr, $is_table) + { + // Borders are disabled in columns - messes up the repositioning in printcolumnbuffer + if ($this->ColActive) { + return; + } // *COLUMNS* + if ($is_table) { + $k = $this->shrin_k; + } else { + $k = 1; + } + $h = (isset($objattr['BORDER-HEIGHT']) ? $objattr['BORDER-HEIGHT'] : 0); + $w = (isset($objattr['BORDER-WIDTH']) ? $objattr['BORDER-WIDTH'] : 0); + $x0 = (isset($objattr['BORDER-X']) ? $objattr['BORDER-X'] : 0); + $y0 = (isset($objattr['BORDER-Y']) ? $objattr['BORDER-Y'] : 0); + + // BORDERS + if ($objattr['border_top']) { + $tbd = $objattr['border_top']; + if (!empty($tbd['s'])) { + $this->_setBorderLine($tbd, $k); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', '', 'T'); + } + $this->Line($x0, $y0, $x0 + $w, $y0); + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($objattr['border_left']) { + $tbd = $objattr['border_left']; + if (!empty($tbd['s'])) { + $this->_setBorderLine($tbd, $k); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', '', 'L'); + } + $this->Line($x0, $y0, $x0, $y0 + $h); + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($objattr['border_right']) { + $tbd = $objattr['border_right']; + if (!empty($tbd['s'])) { + $this->_setBorderLine($tbd, $k); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', '', 'R'); + } + $this->Line($x0 + $w, $y0, $x0 + $w, $y0 + $h); + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + if ($objattr['border_bottom']) { + $tbd = $objattr['border_bottom']; + if (!empty($tbd['s'])) { + $this->_setBorderLine($tbd, $k); + if ($tbd['style'] == 'dotted' || $tbd['style'] == 'dashed') { + $this->_setDashBorder($tbd['style'], '', '', 'B'); + } + $this->Line($x0, $y0 + $h, $x0 + $w, $y0 + $h); + // Reset Corners and Dash off + $this->SetLineJoin(2); + $this->SetLineCap(2); + $this->SetDash(); + } + } + $this->SetDash(); + $this->SetAlpha(1); + } + + /* -- END HTML-CSS -- */ + + function Reset() + { + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + $this->SetAlpha(1); + $this->colorarray = ''; + + $this->spanbgcolorarray = ''; + $this->spanbgcolor = false; + $this->spanborder = false; + $this->spanborddet = []; + + $this->ResetStyles(); + + $this->HREF = ''; + $this->textparam = []; + $this->SetTextOutline(); + + $this->textvar = 0x00; // mPDF 5.7.1 + $this->OTLtags = []; + $this->textshadow = ''; + + $this->currentLang = $this->default_lang; // mPDF 6 + $this->RestrictUnicodeFonts($this->default_available_fonts); // mPDF 6 + $this->SetFont($this->default_font, '', 0, false); + $this->SetFontSize($this->default_font_size, false); + + $this->currentfontfamily = ''; + $this->currentfontsize = ''; + $this->currentfontstyle = ''; + + if ($this->tableLevel && isset($this->table[1][1]['cellLineHeight'])) { + $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); + } else { + if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) { + $this->SetLineHeight('', $this->blk[$this->blklvl]['line_height']); // sets default line height + } + } + + $this->lSpacingCSS = ''; + $this->wSpacingCSS = ''; + $this->fixedlSpacing = false; + $this->minwSpacing = 0; + $this->SetDash(); // restore to no dash + $this->dash_on = false; + $this->dotted_on = false; + $this->divwidth = 0; + $this->divheight = 0; + $this->cellTextAlign = ''; + $this->cellLineHeight = ''; + $this->cellLineStackingStrategy = ''; + $this->cellLineStackingShift = ''; + $this->oldy = -1; + + $bodystyle = []; + + if (isset($this->cssManager->CSS['BODY']['FONT-STYLE'])) { + $bodystyle['FONT-STYLE'] = $this->cssManager->CSS['BODY']['FONT-STYLE']; + } + + if (isset($this->cssManager->CSS['BODY']['FONT-WEIGHT'])) { + $bodystyle['FONT-WEIGHT'] = $this->cssManager->CSS['BODY']['FONT-WEIGHT']; + } + + if (isset($this->cssManager->CSS['BODY']['COLOR'])) { + $bodystyle['COLOR'] = $this->cssManager->CSS['BODY']['COLOR']; + } + + if (isset($bodystyle)) { + $this->setCSS($bodystyle, 'BLOCK', 'BODY'); + } + } + + /* -- HTML-CSS -- */ + + function ReadMetaTags($html) + { + // changes anykey=anyvalue to anykey="anyvalue" (only do this when this happens inside tags) + $regexp = '/ (\\w+?)=([^\\s>"]+)/si'; + $html = preg_replace($regexp, " \$1=\"\$2\"", $html); + if (preg_match('/(.*?)<\/title>/si', $html, $m)) { + $this->SetTitle($m[1]); + } + preg_match_all('/<meta [^>]*?(name|content)="([^>]*?)" [^>]*?(name|content)="([^>]*?)".*?>/si', $html, $aux); + $firstattr = $aux[1]; + $secondattr = $aux[3]; + for ($i = 0; $i < count($aux[0]); $i++) { + $name = ( strtoupper($firstattr[$i]) == "NAME" ) ? strtoupper($aux[2][$i]) : strtoupper($aux[4][$i]); + $content = ( strtoupper($firstattr[$i]) == "CONTENT" ) ? $aux[2][$i] : $aux[4][$i]; + switch ($name) { + case "KEYWORDS": + $this->SetKeywords($content); + break; + case "AUTHOR": + $this->SetAuthor($content); + break; + case "DESCRIPTION": + $this->SetSubject($content); + break; + } + } + } + + function ReadCharset($html) + { + // Charset conversion + if ($this->allow_charset_conversion) { + if (preg_match('/<head.*charset=([^\'\"\s]*).*<\/head>/si', $html, $m)) { + if (strtoupper($m[1]) != 'UTF-8') { + $this->charset_in = strtoupper($m[1]); + } + } + } + } + + function setCSS($arrayaux, $type = '', $tag = '') + { + // type= INLINE | BLOCK | TABLECELL // tag= BODY + if (!is_array($arrayaux)) { + return; // Removes PHP Warning + } + + // mPDF 5.7.3 inline text-decoration parameters + $preceeding_fontkey = $this->FontFamily . $this->FontStyle; + $preceeding_fontsize = $this->FontSize; + $spanbordset = false; + $spanbgset = false; + // mPDF 6 + $prevlevel = (($this->blklvl == 0) ? 0 : $this->blklvl - 1); + + // Set font size first so that e.g. MARGIN 0.83em works on font size for this element + if (isset($arrayaux['FONT-SIZE'])) { + $v = $arrayaux['FONT-SIZE']; + $firstLetter = substr($v, 0, 1); + if (is_numeric($firstLetter) || ($firstLetter === '.')) { + if ($type == 'BLOCK' && $this->blklvl > 0 && isset($this->blk[$this->blklvl - 1]['InlineProperties']) && isset($this->blk[$this->blklvl - 1]['InlineProperties']['size'])) { + $mmsize = $this->sizeConverter->convert($v, $this->blk[$this->blklvl - 1]['InlineProperties']['size']); + } elseif ($type == 'TABLECELL') { + $mmsize = $this->sizeConverter->convert($v, $this->default_font_size / Mpdf::SCALE); + } else { + $mmsize = $this->sizeConverter->convert($v, $this->FontSize); + } + $this->SetFontSize($mmsize * (Mpdf::SCALE), false); // Get size in points (pt) + } else { + $v = strtoupper($v); + if (isset($this->fontsizes[$v])) { + $this->SetFontSize($this->fontsizes[$v] * $this->default_font_size, false); + } + } + if ($tag == 'BODY') { + $this->SetDefaultFontSize($this->FontSizePt); + } + } + + // mPDF 6 + if (isset($arrayaux['LANG']) && $arrayaux['LANG']) { + if ($this->autoLangToFont && !$this->usingCoreFont) { + if ($arrayaux['LANG'] != $this->default_lang && $arrayaux['LANG'] != 'UTF-8') { + list ($coreSuitable, $mpdf_pdf_unifont) = $this->languageToFont->getLanguageOptions($arrayaux['LANG'], $this->useAdobeCJK); + if ($mpdf_pdf_unifont) { + $arrayaux['FONT-FAMILY'] = $mpdf_pdf_unifont; + } + if ($tag == 'BODY') { + $this->default_lang = $arrayaux['LANG']; + } + } + } + $this->currentLang = $arrayaux['LANG']; + } + + // FOR INLINE and BLOCK OR 'BODY' + if (isset($arrayaux['FONT-FAMILY'])) { + $v = $arrayaux['FONT-FAMILY']; + // If it is a font list, get all font types + $aux_fontlist = explode(",", $v); + $found = 0; + foreach ($aux_fontlist as $f) { + $fonttype = trim($f); + $fonttype = preg_replace('/["\']*(.*?)["\']*/', '\\1', $fonttype); + $fonttype = preg_replace('/ /', '', $fonttype); + $v = strtolower(trim($fonttype)); + if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { + $v = $this->fonttrans[$v]; + } + if ((!$this->onlyCoreFonts && in_array($v, $this->available_unifonts)) || + in_array($v, ['ccourier', 'ctimes', 'chelvetica']) || + ($this->onlyCoreFonts && in_array($v, ['courier', 'times', 'helvetica', 'arial'])) || + in_array($v, ['sjis', 'uhc', 'big5', 'gb'])) { + $fonttype = $v; + $found = 1; + break; + } + } + if (!$found) { + foreach ($aux_fontlist as $f) { + $fonttype = trim($f); + $fonttype = preg_replace('/["\']*(.*?)["\']*/', '\\1', $fonttype); + $fonttype = preg_replace('/ /', '', $fonttype); + $v = strtolower(trim($fonttype)); + if (isset($this->fonttrans[$v]) && $this->fonttrans[$v]) { + $v = $this->fonttrans[$v]; + } + if (in_array($v, $this->sans_fonts) || in_array($v, $this->serif_fonts) || in_array($v, $this->mono_fonts)) { + $fonttype = $v; + break; + } + } + } + + if ($tag == 'BODY') { + $this->SetDefaultFont($fonttype); + } + $this->SetFont($fonttype, $this->currentfontstyle, 0, false); + } else { + $this->SetFont($this->currentfontfamily, $this->currentfontstyle, 0, false); + } + + foreach ($arrayaux as $k => $v) { + if ($type != 'INLINE' && $tag != 'BODY' && $type != 'TABLECELL') { + switch ($k) { + // BORDERS + case 'BORDER-TOP': + $this->blk[$this->blklvl]['border_top'] = $this->border_details($v); + if ($this->blk[$this->blklvl]['border_top']['s']) { + $this->blk[$this->blklvl]['border'] = 1; + } + break; + case 'BORDER-BOTTOM': + $this->blk[$this->blklvl]['border_bottom'] = $this->border_details($v); + if ($this->blk[$this->blklvl]['border_bottom']['s']) { + $this->blk[$this->blklvl]['border'] = 1; + } + break; + case 'BORDER-LEFT': + $this->blk[$this->blklvl]['border_left'] = $this->border_details($v); + if ($this->blk[$this->blklvl]['border_left']['s']) { + $this->blk[$this->blklvl]['border'] = 1; + } + break; + case 'BORDER-RIGHT': + $this->blk[$this->blklvl]['border_right'] = $this->border_details($v); + if ($this->blk[$this->blklvl]['border_right']['s']) { + $this->blk[$this->blklvl]['border'] = 1; + } + break; + + // PADDING + case 'PADDING-TOP': + $this->blk[$this->blklvl]['padding_top'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'PADDING-BOTTOM': + $this->blk[$this->blklvl]['padding_bottom'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'PADDING-LEFT': + if (($tag == 'UL' || $tag == 'OL') && $v == 'auto') { + $this->blk[$this->blklvl]['padding_left'] = 'auto'; + break; + } + $this->blk[$this->blklvl]['padding_left'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'PADDING-RIGHT': + if (($tag == 'UL' || $tag == 'OL') && $v == 'auto') { + $this->blk[$this->blklvl]['padding_right'] = 'auto'; + break; + } + $this->blk[$this->blklvl]['padding_right'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + + // MARGINS + case 'MARGIN-TOP': + $tmp = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + if (isset($this->blk[$this->blklvl]['lastbottommargin'])) { + if ($tmp > $this->blk[$this->blklvl]['lastbottommargin']) { + $tmp -= $this->blk[$this->blklvl]['lastbottommargin']; + } else { + $tmp = 0; + } + } + $this->blk[$this->blklvl]['margin_top'] = $tmp; + break; + case 'MARGIN-BOTTOM': + $this->blk[$this->blklvl]['margin_bottom'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'MARGIN-LEFT': + $this->blk[$this->blklvl]['margin_left'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'MARGIN-RIGHT': + $this->blk[$this->blklvl]['margin_right'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + + /* -- BORDER-RADIUS -- */ + case 'BORDER-TOP-LEFT-RADIUS-H': + $this->blk[$this->blklvl]['border_radius_TL_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-TOP-LEFT-RADIUS-V': + $this->blk[$this->blklvl]['border_radius_TL_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-TOP-RIGHT-RADIUS-H': + $this->blk[$this->blklvl]['border_radius_TR_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-TOP-RIGHT-RADIUS-V': + $this->blk[$this->blklvl]['border_radius_TR_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-BOTTOM-LEFT-RADIUS-H': + $this->blk[$this->blklvl]['border_radius_BL_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-BOTTOM-LEFT-RADIUS-V': + $this->blk[$this->blklvl]['border_radius_BL_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-BOTTOM-RIGHT-RADIUS-H': + $this->blk[$this->blklvl]['border_radius_BR_H'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + case 'BORDER-BOTTOM-RIGHT-RADIUS-V': + $this->blk[$this->blklvl]['border_radius_BR_V'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + break; + /* -- END BORDER-RADIUS -- */ + + case 'BOX-SHADOW': + $bs = $this->cssManager->setCSSboxshadow($v); + if ($bs) { + $this->blk[$this->blklvl]['box_shadow'] = $bs; + } + break; + + case 'BACKGROUND-CLIP': + if (strtoupper($v) == 'PADDING-BOX') { + $this->blk[$this->blklvl]['background_clip'] = 'padding-box'; + } elseif (strtoupper($v) == 'CONTENT-BOX') { + $this->blk[$this->blklvl]['background_clip'] = 'content-box'; + } + break; + + case 'PAGE-BREAK-AFTER': + if (strtoupper($v) == 'AVOID') { + $this->blk[$this->blklvl]['page_break_after_avoid'] = true; + } elseif (strtoupper($v) == 'ALWAYS' || strtoupper($v) == 'LEFT' || strtoupper($v) == 'RIGHT') { + $this->blk[$this->blklvl]['page_break_after'] = strtoupper($v); + } + break; + + // mPDF 6 pagebreaktype + case 'BOX-DECORATION-BREAK': + if (strtoupper($v) == 'CLONE') { + $this->blk[$this->blklvl]['box_decoration_break'] = 'clone'; + } elseif (strtoupper($v) == 'SLICE') { + $this->blk[$this->blklvl]['box_decoration_break'] = 'slice'; + } + break; + + case 'WIDTH': + if (strtoupper($v) != 'AUTO') { + $this->blk[$this->blklvl]['css_set_width'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false); + } + break; + + // mPDF 6 Lists + // LISTS + case 'LIST-STYLE-TYPE': + $this->blk[$this->blklvl]['list_style_type'] = strtolower($v); + break; + case 'LIST-STYLE-IMAGE': + $this->blk[$this->blklvl]['list_style_image'] = strtolower($v); + break; + case 'LIST-STYLE-POSITION': + $this->blk[$this->blklvl]['list_style_position'] = strtolower($v); + break; + }//end of switch($k) + } + + + if ($type != 'INLINE' && $type != 'TABLECELL') { // All block-level, including BODY tag + switch ($k) { + case 'TEXT-INDENT': + // Computed value - to inherit + $this->blk[$this->blklvl]['text_indent'] = $this->sizeConverter->convert($v, $this->blk[$prevlevel]['inner_width'], $this->FontSize, false) . 'mm'; + break; + + case 'MARGIN-COLLAPSE': // Custom tag to collapse margins at top and bottom of page + if (strtoupper($v) == 'COLLAPSE') { + $this->blk[$this->blklvl]['margin_collapse'] = true; + } + break; + + case 'LINE-HEIGHT': + $this->blk[$this->blklvl]['line_height'] = $this->fixLineheight($v); + if (!$this->blk[$this->blklvl]['line_height']) { + $this->blk[$this->blklvl]['line_height'] = 'N'; + } // mPDF 6 + break; + + // mPDF 6 + case 'LINE-STACKING-STRATEGY': + $this->blk[$this->blklvl]['line_stacking_strategy'] = strtolower($v); + break; + + case 'LINE-STACKING-SHIFT': + $this->blk[$this->blklvl]['line_stacking_shift'] = strtolower($v); + break; + + case 'TEXT-ALIGN': // left right center justify + switch (strtoupper($v)) { + case 'LEFT': + $this->blk[$this->blklvl]['align'] = "L"; + break; + case 'CENTER': + $this->blk[$this->blklvl]['align'] = "C"; + break; + case 'RIGHT': + $this->blk[$this->blklvl]['align'] = "R"; + break; + case 'JUSTIFY': + $this->blk[$this->blklvl]['align'] = "J"; + break; + } + break; + + /* -- BACKGROUNDS -- */ + case 'BACKGROUND-GRADIENT': + if ($type == 'BLOCK') { + $this->blk[$this->blklvl]['gradient'] = $v; + } + break; + /* -- END BACKGROUNDS -- */ + + case 'DIRECTION': + if ($v) { + $this->blk[$this->blklvl]['direction'] = strtolower($v); + } + break; + } + } + + // FOR INLINE ONLY + if ($type == 'INLINE') { + switch ($k) { + case 'DISPLAY': + if (strtoupper($v) == 'NONE') { + $this->inlineDisplayOff = true; + } + break; + case 'DIRECTION': + break; + } + } + // FOR INLINE ONLY + if ($type == 'INLINE') { + switch ($k) { + // BORDERS + case 'BORDER-TOP': + $this->spanborddet['T'] = $this->border_details($v); + $this->spanborder = true; + $spanbordset = true; + break; + case 'BORDER-BOTTOM': + $this->spanborddet['B'] = $this->border_details($v); + $this->spanborder = true; + $spanbordset = true; + break; + case 'BORDER-LEFT': + $this->spanborddet['L'] = $this->border_details($v); + $this->spanborder = true; + $spanbordset = true; + break; + case 'BORDER-RIGHT': + $this->spanborddet['R'] = $this->border_details($v); + $this->spanborder = true; + $spanbordset = true; + break; + case 'VISIBILITY': // block is set in OpenTag + $v = strtolower($v); + if ($v == 'visible' || $v == 'hidden' || $v == 'printonly' || $v == 'screenonly') { + $this->textparam['visibility'] = $v; + } + break; + }//end of switch($k) + } + + if ($type != 'TABLECELL') { + // FOR INLINE and BLOCK + switch ($k) { + case 'TEXT-ALIGN': // left right center justify + if (strtoupper($v) == 'NOJUSTIFY' && $this->blk[$this->blklvl]['align'] == "J") { + $this->blk[$this->blklvl]['align'] = ""; + } + break; + // bgcolor only - to stay consistent with original html2fpdf + case 'BACKGROUND': + case 'BACKGROUND-COLOR': + $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); + if ($cor) { + if ($tag == 'BODY') { + $this->bodyBackgroundColor = $cor; + } elseif ($type == 'INLINE') { + $this->spanbgcolorarray = $cor; + $this->spanbgcolor = true; + $spanbgset = true; + } else { + $this->blk[$this->blklvl]['bgcolorarray'] = $cor; + $this->blk[$this->blklvl]['bgcolor'] = true; + } + } elseif ($type != 'INLINE') { + if ($this->ColActive) { + $this->blk[$this->blklvl]['bgcolorarray'] = $this->blk[$prevlevel]['bgcolorarray']; + $this->blk[$this->blklvl]['bgcolor'] = $this->blk[$prevlevel]['bgcolor']; + } + } + break; + + case 'VERTICAL-ALIGN': // super and sub only dealt with here e.g. <SUB> and <SUP> + switch (strtoupper($v)) { + case 'SUPER': + $this->textvar = ($this->textvar | TextVars::FA_SUPERSCRIPT); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + $this->textparam['text-baseline'] += ($this->baselineSup) * $preceeding_fontsize; + } else { + $this->textparam['text-baseline'] = ($this->baselineSup) * $preceeding_fontsize; + } + break; + case 'SUB': + $this->textvar = ($this->textvar | TextVars::FA_SUBSCRIPT); + $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + $this->textparam['text-baseline'] += ($this->baselineSub) * $preceeding_fontsize; + } else { + $this->textparam['text-baseline'] = ($this->baselineSub) * $preceeding_fontsize; + } + break; + case 'BASELINE': + $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); + $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + unset($this->textparam['text-baseline']); + } + break; + // mPDF 5.7.3 inline text-decoration parameters + default: + $lh = $this->_computeLineheight($this->blk[$this->blklvl]['line_height']); + $sz = $this->sizeConverter->convert($v, $lh, $this->FontSize, false); + $this->textvar = ($this->textvar & ~TextVars::FA_SUBSCRIPT); + $this->textvar = ($this->textvar & ~TextVars::FA_SUPERSCRIPT); + if ($sz) { + if ($sz > 0) { + $this->textvar = ($this->textvar | TextVars::FA_SUPERSCRIPT); + } else { + $this->textvar = ($this->textvar | TextVars::FA_SUBSCRIPT); + } + if (isset($this->textparam['text-baseline'])) { + $this->textparam['text-baseline'] += $sz; + } else { + $this->textparam['text-baseline'] = $sz; + } + } + } + break; + }//end of switch($k) + } + + + // FOR ALL + switch ($k) { + case 'LETTER-SPACING': + $this->lSpacingCSS = $v; + if (($this->lSpacingCSS || $this->lSpacingCSS === '0') && strtoupper($this->lSpacingCSS) != 'NORMAL') { + $this->fixedlSpacing = $this->sizeConverter->convert($this->lSpacingCSS, $this->FontSize); + } + break; + + case 'WORD-SPACING': + $this->wSpacingCSS = $v; + if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') { + $this->minwSpacing = $this->sizeConverter->convert($this->wSpacingCSS, $this->FontSize); + } + break; + + case 'FONT-STYLE': // italic normal oblique + switch (strtoupper($v)) { + case 'ITALIC': + case 'OBLIQUE': + $this->SetStyle('I', true); + break; + case 'NORMAL': + $this->SetStyle('I', false); + break; + } + break; + + case 'FONT-WEIGHT': // normal bold // Does not support: bolder, lighter, 100..900(step value=100) + switch (strtoupper($v)) { + case 'BOLD': + $this->SetStyle('B', true); + break; + case 'NORMAL': + $this->SetStyle('B', false); + break; + } + break; + + case 'FONT-KERNING': + if (strtoupper($v) == 'NORMAL' || (strtoupper($v) == 'AUTO' && $this->useKerning)) { + /* -- OTL -- */ + if ($this->CurrentFont['haskernGPOS']) { + if (isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] .= ' kern'; + } else { + $this->OTLtags['Plus'] = ' kern'; + } + } /* -- END OTL -- */ else { // *OTL* + $this->textvar = ($this->textvar | TextVars::FC_KERNING); + } // *OTL* + } elseif (strtoupper($v) == 'NONE' || (strtoupper($v) == 'AUTO' && !$this->useKerning)) { + if (isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = str_replace('kern', '', $this->OTLtags['Plus']); // *OTL* + } + if (isset($this->OTLtags['FFPlus'])) { + $this->OTLtags['FFPlus'] = preg_replace('/kern[\d]*/', '', $this->OTLtags['FFPlus']); + } + $this->textvar = ($this->textvar & ~TextVars::FC_KERNING); + } + break; + + /* -- OTL -- */ + case 'FONT-LANGUAGE-OVERRIDE': + $v = strtoupper($v); + if (strpos($v, 'NORMAL') !== false) { + $this->fontLanguageOverride = ''; + } else { + $this->fontLanguageOverride = trim($v); + } + break; + + + case 'FONT-VARIANT-POSITION': + if (isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = str_replace(['sups', 'subs'], '', $this->OTLtags['Plus']); + } + switch (strtoupper($v)) { + case 'SUPER': + $this->OTLtags['Plus'] .= ' sups'; + break; + case 'SUB': + $this->OTLtags['Plus'] .= ' subs'; + break; + case 'NORMAL': + break; + } + break; + + case 'FONT-VARIANT-CAPS': + $v = strtoupper($v); + if (!isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = ''; + } + $this->OTLtags['Plus'] = str_replace(['c2sc', 'smcp', 'c2pc', 'pcap', 'unic', 'titl'], '', $this->OTLtags['Plus']); + $this->textvar = ($this->textvar & ~TextVars::FC_SMALLCAPS); // ?????????????? <small-caps> + if (strpos($v, 'ALL-SMALL-CAPS') !== false) { + $this->OTLtags['Plus'] .= ' c2sc smcp'; + } elseif (strpos($v, 'SMALL-CAPS') !== false) { + if (isset($this->CurrentFont['hassmallcapsGSUB']) && $this->CurrentFont['hassmallcapsGSUB']) { + $this->OTLtags['Plus'] .= ' smcp'; + } else { + $this->textvar = ($this->textvar | TextVars::FC_SMALLCAPS); + } + } elseif (strpos($v, 'ALL-PETITE-CAPS') !== false) { + $this->OTLtags['Plus'] .= ' c2pc pcap'; + } elseif (strpos($v, 'PETITE-CAPS') !== false) { + $this->OTLtags['Plus'] .= ' pcap'; + } elseif (strpos($v, 'UNICASE') !== false) { + $this->OTLtags['Plus'] .= ' unic'; + } elseif (strpos($v, 'TITLING-CAPS') !== false) { + $this->OTLtags['Plus'] .= ' titl'; + } + break; + + case 'FONT-VARIANT-LIGATURES': + $v = strtoupper($v); + if (!isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = ''; + } + if (!isset($this->OTLtags['Minus'])) { + $this->OTLtags['Minus'] = ''; + } + if (strpos($v, 'NORMAL') !== false) { + $this->OTLtags['Minus'] = str_replace(['liga', 'clig', 'calt'], '', $this->OTLtags['Minus']); + $this->OTLtags['Plus'] = str_replace(['dlig', 'hlig'], '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'NONE') !== false) { + $this->OTLtags['Minus'] .= ' liga clig calt'; + $this->OTLtags['Plus'] = str_replace(['dlig', 'hlig'], '', $this->OTLtags['Plus']); + } + if (strpos($v, 'NO-COMMON-LIGATURES') !== false) { + $this->OTLtags['Minus'] .= ' liga clig'; + } elseif (strpos($v, 'COMMON-LIGATURES') !== false) { + $this->OTLtags['Minus'] = str_replace(['liga', 'clig'], '', $this->OTLtags['Minus']); + } + if (strpos($v, 'NO-CONTEXTUAL') !== false) { + $this->OTLtags['Minus'] .= ' calt'; + } elseif (strpos($v, 'CONTEXTUAL') !== false) { + $this->OTLtags['Minus'] = str_replace('calt', '', $this->OTLtags['Minus']); + } + if (strpos($v, 'NO-DISCRETIONARY-LIGATURES') !== false) { + $this->OTLtags['Plus'] = str_replace('dlig', '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'DISCRETIONARY-LIGATURES') !== false) { + $this->OTLtags['Plus'] .= ' dlig'; + } + if (strpos($v, 'NO-HISTORICAL-LIGATURES') !== false) { + $this->OTLtags['Plus'] = str_replace('hlig', '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'HISTORICAL-LIGATURES') !== false) { + $this->OTLtags['Plus'] .= ' hlig'; + } + + break; + + case 'FONT-VARIANT-NUMERIC': + $v = strtoupper($v); + if (!isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = ''; + } + if (strpos($v, 'NORMAL') !== false) { + $this->OTLtags['Plus'] = str_replace(['ordn', 'zero', 'lnum', 'onum', 'pnum', 'tnum', 'frac', 'afrc'], '', $this->OTLtags['Plus']); + } + if (strpos($v, 'ORDINAL') !== false) { + $this->OTLtags['Plus'] .= ' ordn'; + } + if (strpos($v, 'SLASHED-ZERO') !== false) { + $this->OTLtags['Plus'] .= ' zero'; + } + if (strpos($v, 'LINING-NUMS') !== false) { + $this->OTLtags['Plus'] .= ' lnum'; + $this->OTLtags['Plus'] = str_replace('onum', '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'OLDSTYLE-NUMS') !== false) { + $this->OTLtags['Plus'] .= ' onum'; + $this->OTLtags['Plus'] = str_replace('lnum', '', $this->OTLtags['Plus']); + } + if (strpos($v, 'PROPORTIONAL-NUMS') !== false) { + $this->OTLtags['Plus'] .= ' pnum'; + $this->OTLtags['Plus'] = str_replace('tnum', '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'TABULAR-NUMS') !== false) { + $this->OTLtags['Plus'] .= ' tnum'; + $this->OTLtags['Plus'] = str_replace('pnum', '', $this->OTLtags['Plus']); + } + if (strpos($v, 'DIAGONAL-FRACTIONS') !== false) { + $this->OTLtags['Plus'] .= ' frac'; + $this->OTLtags['Plus'] = str_replace('afrc', '', $this->OTLtags['Plus']); + } elseif (strpos($v, 'STACKED-FRACTIONS') !== false) { + $this->OTLtags['Plus'] .= ' afrc'; + $this->OTLtags['Plus'] = str_replace('frac', '', $this->OTLtags['Plus']); + } + break; + + case 'FONT-VARIANT-ALTERNATES': // Only supports historical-forms + $v = strtoupper($v); + if (!isset($this->OTLtags['Plus'])) { + $this->OTLtags['Plus'] = ''; + } + if (strpos($v, 'NORMAL') !== false) { + $this->OTLtags['Plus'] = str_replace('hist', '', $this->OTLtags['Plus']); + } + if (strpos($v, 'HISTORICAL-FORMS') !== false) { + $this->OTLtags['Plus'] .= ' hist'; + } + break; + + + case 'FONT-FEATURE-SETTINGS': + $v = strtolower($v); + if (strpos($v, 'normal') !== false) { + $this->OTLtags['FFMinus'] = ''; + $this->OTLtags['FFPlus'] = ''; + } else { + if (!isset($this->OTLtags['FFPlus'])) { + $this->OTLtags['FFPlus'] = ''; + } + if (!isset($this->OTLtags['FFMinus'])) { + $this->OTLtags['FFMinus'] = ''; + } + $tags = preg_split('/[,]/', $v); + foreach ($tags as $t) { + if (preg_match('/[\"\']([a-zA-Z0-9]{4})[\"\']\s*(on|off|\d*){0,1}/', $t, $m)) { + if ($m[2] == 'off' || $m[2] === '0') { + if (strpos($this->OTLtags['FFMinus'], $m[1]) === false) { + $this->OTLtags['FFMinus'] .= ' ' . $m[1]; + } + $this->OTLtags['FFPlus'] = preg_replace('/' . $m[1] . '[\d]*/', '', $this->OTLtags['FFPlus']); + } else { + if ($m[2] == 'on') { + $m[2] = '1'; + } + if (strpos($this->OTLtags['FFPlus'], $m[1]) === false) { + $this->OTLtags['FFPlus'] .= ' ' . $m[1] . $m[2]; + } + $this->OTLtags['FFMinus'] = str_replace($m[1], '', $this->OTLtags['FFMinus']); + } + } + } + } + break; + /* -- END OTL -- */ + + + case 'TEXT-TRANSFORM': // none uppercase lowercase // Does support: capitalize + switch (strtoupper($v)) { // Not working 100% + case 'CAPITALIZE': + $this->textvar = ($this->textvar | TextVars::FT_CAPITALIZE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 + break; + case 'UPPERCASE': + $this->textvar = ($this->textvar | TextVars::FT_UPPERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 + break; + case 'LOWERCASE': + $this->textvar = ($this->textvar | TextVars::FT_LOWERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 + break; + case 'NONE': + break; + $this->textvar = ($this->textvar & ~TextVars::FT_UPPERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_LOWERCASE); // mPDF 5.7.1 + $this->textvar = ($this->textvar & ~TextVars::FT_CAPITALIZE); // mPDF 5.7.1 + } + break; + + case 'TEXT-SHADOW': + $ts = $this->cssManager->setCSStextshadow($v); + if ($ts) { + $this->textshadow = $ts; + } + break; + + case 'HYPHENS': + if (strtoupper($v) == 'NONE') { + $this->textparam['hyphens'] = 2; + } elseif (strtoupper($v) == 'AUTO') { + $this->textparam['hyphens'] = 1; + } elseif (strtoupper($v) == 'MANUAL') { + $this->textparam['hyphens'] = 0; + } + break; + + case 'TEXT-OUTLINE': + if (strtoupper($v) == 'NONE') { + $this->textparam['outline-s'] = false; + } + break; + + case 'TEXT-OUTLINE-WIDTH': + case 'OUTLINE-WIDTH': + switch (strtoupper($v)) { + case 'THIN': + $v = '0.03em'; + break; + case 'MEDIUM': + $v = '0.05em'; + break; + case 'THICK': + $v = '0.07em'; + break; + } + $w = $this->sizeConverter->convert($v, $this->FontSize, $this->FontSize); + if ($w) { + $this->textparam['outline-WIDTH'] = $w; + $this->textparam['outline-s'] = true; + } else { + $this->textparam['outline-s'] = false; + } + break; + + case 'TEXT-OUTLINE-COLOR': + case 'OUTLINE-COLOR': + if (strtoupper($v) == 'INVERT') { + if ($this->colorarray) { + $cor = $this->colorarray; + $this->textparam['outline-COLOR'] = $this->colorConverter->invert($cor); + } else { + $this->textparam['outline-COLOR'] = $this->colorConverter->convert(255, $this->PDFAXwarnings); + } + } else { + $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); + if ($cor) { + $this->textparam['outline-COLOR'] = $cor; + } + } + break; + + case 'COLOR': // font color + $cor = $this->colorConverter->convert($v, $this->PDFAXwarnings); + if ($cor) { + $this->colorarray = $cor; + $this->SetTColor($cor); + } + break; + }//end of switch($k) + }//end of foreach + // mPDF 5.7.3 inline text-decoration parameters + // Needs to be set at the end - after vertical-align = super/sub, so that textparam['text-baseline'] is set + if (isset($arrayaux['TEXT-DECORATION'])) { + $v = $arrayaux['TEXT-DECORATION']; // none underline line-through (strikeout) // Does not support: blink + if (stristr($v, 'LINE-THROUGH')) { + $this->textvar = ($this->textvar | TextVars::FD_LINETHROUGH); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + $this->textparam['s-decoration']['baseline'] = $this->textparam['text-baseline']; + } else { + $this->textparam['s-decoration']['baseline'] = 0; + } + $this->textparam['s-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; + $this->textparam['s-decoration']['fontsize'] = $this->FontSize; + $this->textparam['s-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG + } + if (stristr($v, 'UNDERLINE')) { + $this->textvar = ($this->textvar | TextVars::FD_UNDERLINE); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + $this->textparam['u-decoration']['baseline'] = $this->textparam['text-baseline']; + } else { + $this->textparam['u-decoration']['baseline'] = 0; + } + $this->textparam['u-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; + $this->textparam['u-decoration']['fontsize'] = $this->FontSize; + $this->textparam['u-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG + } + if (stristr($v, 'OVERLINE')) { + $this->textvar = ($this->textvar | TextVars::FD_OVERLINE); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['text-baseline'])) { + $this->textparam['o-decoration']['baseline'] = $this->textparam['text-baseline']; + } else { + $this->textparam['o-decoration']['baseline'] = 0; + } + $this->textparam['o-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; + $this->textparam['o-decoration']['fontsize'] = $this->FontSize; + $this->textparam['o-decoration']['color'] = strtoupper($this->TextColor); // change 0 0 0 rg to 0 0 0 RG + } + if (stristr($v, 'NONE')) { + $this->textvar = ($this->textvar & ~TextVars::FD_UNDERLINE); + $this->textvar = ($this->textvar & ~TextVars::FD_LINETHROUGH); + $this->textvar = ($this->textvar & ~TextVars::FD_OVERLINE); + // mPDF 5.7.3 inline text-decoration parameters + if (isset($this->textparam['u-decoration'])) { + unset($this->textparam['u-decoration']); + } + if (isset($this->textparam['s-decoration'])) { + unset($this->textparam['s-decoration']); + } + if (isset($this->textparam['o-decoration'])) { + unset($this->textparam['o-decoration']); + } + } + } + // mPDF 6 + if ($spanbordset) { // BORDER has been set on this INLINE element + if (isset($this->textparam['text-baseline'])) { + $this->textparam['bord-decoration']['baseline'] = $this->textparam['text-baseline']; + } else { + $this->textparam['bord-decoration']['baseline'] = 0; + } + $this->textparam['bord-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; + $this->textparam['bord-decoration']['fontsize'] = $this->FontSize; + } + if ($spanbgset) { // BACKGROUND[-COLOR] has been set on this INLINE element + if (isset($this->textparam['text-baseline'])) { + $this->textparam['bg-decoration']['baseline'] = $this->textparam['text-baseline']; + } else { + $this->textparam['bg-decoration']['baseline'] = 0; + } + $this->textparam['bg-decoration']['fontkey'] = $this->FontFamily . $this->FontStyle; + $this->textparam['bg-decoration']['fontsize'] = $this->FontSize; + } + } + + /* -- END HTML-CSS -- */ + + function SetStyle($tag, $enable) + { + $this->$tag = $enable; + $style = ''; + foreach (['B', 'I'] as $s) { + if ($this->$s) { + $style .= $s; + } + } + $this->currentfontstyle = $style; + $this->SetFont('', $style, 0, false); + } + + // Set multiple styles at one time + function SetStylesArray($arr) + { + $style = ''; + foreach (['B', 'I'] as $s) { + if (isset($arr[$s])) { + if ($arr[$s]) { + $this->$s = true; + $style .= $s; + } else { + $this->$s = false; + } + } elseif ($this->$s) { + $style .= $s; + } + } + $this->currentfontstyle = $style; + $this->SetFont('', $style, 0, false); + } + + // Set multiple styles at one $str e.g. "BI" + function SetStyles($str) + { + $style = ''; + foreach (['B', 'I'] as $s) { + if (strpos($str, $s) !== false) { + $this->$s = true; + $style .= $s; + } else { + $this->$s = false; + } + } + $this->currentfontstyle = $style; + $this->SetFont('', $style, 0, false); + } + + function ResetStyles() + { + foreach (['B', 'I'] as $s) { + $this->$s = false; + } + $this->currentfontstyle = ''; + $this->SetFont('', '', 0, false); + } + + function DisableTags($str = '') + { + if ($str == '') { // enable all tags + // Insert new supported tags in the long string below. + $this->enabledtags = "<a><acronym><address><article><aside><b><bdi><bdo><big><blockquote><br><caption><center><cite><code><del><details><dd><div><dl><dt><em><fieldset><figcaption><figure><font><form><h1><h2><h3><h4><h5><h6><hgroup><hr><i><img><input><ins><kbd><legend><li><main><mark><meter><nav><ol><option><p><pre><progress><q><s><samp><section><select><small><span><strike><strong><sub><summary><sup><table><tbody><td><template><textarea><tfoot><th><thead><time><tr><tt><u><ul><var><footer><header><annotation><bookmark><textcircle><barcode><dottab><indexentry><indexinsert><watermarktext><watermarkimage><tts><ttz><tta><column_break><columnbreak><newcolumn><newpage><page_break><pagebreak><formfeed><columns><toc><tocentry><tocpagebreak><pageheader><pagefooter><setpageheader><setpagefooter><sethtmlpageheader><sethtmlpagefooter>"; + } else { + $str = explode(",", $str); + foreach ($str as $v) { + $this->enabledtags = str_replace(trim($v), '', $this->enabledtags); + } + } + } + + /* -- TABLES -- */ + + function TableCheckMinWidth($maxwidth, $forcewrap = 0, $textbuffer = [], $checkletter = false) + { + // mPDF 6 + $acclength = 0; // mPDF 6 (accumulated length across > 1 chunk) + $acclongest = 0; // mPDF 6 (accumulated length max across > 1 chunk) + $biggestword = 0; + $toonarrow = false; + if ((count($textbuffer) == 0) or ( (count($textbuffer) == 1) && ($textbuffer[0][0] == ''))) { + return 0; + } + + foreach ($textbuffer as $chunk) { + $line = $chunk[0]; + $OTLdata = (isset($chunk[18]) ? $chunk[18] : null); + + // mPDF ITERATION + if ($this->iterationCounter) { + $line = preg_replace('/{iteration ([a-zA-Z0-9_]+)}/', '\\1', $line); + } + + // IMAGES & FORM ELEMENTS + if (substr($line, 0, 3) == Mpdf::OBJECT_IDENTIFIER) { // inline object - FORM element or IMAGE! + $objattr = $this->_getObjAttr($line); + if ($objattr['type'] != 'hr' && isset($objattr['width']) && ($objattr['width'] / $this->shrin_k) > ($maxwidth + 0.0001)) { + if (($objattr['width'] / $this->shrin_k) > $biggestword) { + $biggestword = ($objattr['width'] / $this->shrin_k); + } + $toonarrow = true; + } + continue; + } + + if ($line == "\n") { + $acclength = 0; // mPDF 6 (accumulated length across > 1 chunk) + continue; + } + $line = trim($line); + if (!empty($OTLdata)) { + $this->otl->trimOTLdata($OTLdata, true, true); + } // *OTL* + // SET FONT SIZE/STYLE from $chunk[n] + // FONTSIZE + if (isset($chunk[11]) and $chunk[11] != '') { + if ($this->shrin_k) { + $this->SetFontSize($chunk[11] / $this->shrin_k, false); + } else { + $this->SetFontSize($chunk[11], false); + } + } + // FONTFAMILY + if (isset($chunk[4]) and $chunk[4] != '') { + $font = $this->SetFont($chunk[4], $this->FontStyle, 0, false); + } + // B I + if (isset($chunk[2]) and $chunk[2] != '') { + $this->SetStyles($chunk[2]); + } + + $lbw = $rbw = 0; // Border widths + if (isset($chunk[16]) && !empty($chunk[16])) { // Border + $this->spanborddet = $chunk[16]; + $lbw = (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0); + $rbw = (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0); + } + if (isset($chunk[15])) { // Word spacing + $this->wSpacingCSS = $chunk[15]; + if ($this->wSpacingCSS && strtoupper($this->wSpacingCSS) != 'NORMAL') { + $this->minwSpacing = $this->sizeConverter->convert($this->wSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 + } + } + if (isset($chunk[14])) { // Letter spacing + $this->lSpacingCSS = $chunk[14]; + if (($this->lSpacingCSS || $this->lSpacingCSS === '0') && strtoupper($this->lSpacingCSS) != 'NORMAL') { + $this->fixedlSpacing = $this->sizeConverter->convert($this->lSpacingCSS, $this->FontSize) / $this->shrin_k; // mPDF 5.7.3 + } + } + if (isset($chunk[8])) { // mPDF 5.7.1 + $this->textvar = $chunk[8]; + } + + // mPDF 6 + // If overflow==wrap ($checkletter) OR (No word breaks and contains CJK) + if ($checkletter || (!preg_match('/(\xe2\x80\x8b| )/', trim($line)) && preg_match("/([" . $this->pregCJKchars . "])/u", $line) )) { + if (preg_match("/([" . $this->pregCJKchars . "])/u", $line)) { + $checkCJK = true; + } else { + $checkCJK = false; + } + + $letters = preg_split('//u', $line); + foreach ($letters as $k => $letter) { + // mPDF 6 + if ($checkCJK) { + if (preg_match("/[" . $this->CJKleading . "]/u", $letter) && $k > 0) { + $letter = $letters[$k - 1] . $letter; + } + if (preg_match("/[" . $this->CJKfollowing . "]/u", $letter) && $k < (count($letters) - 1)) { + $letter = $letter . $letters[$k + 1]; + } + } + + $letterwidth = $this->GetStringWidth($letter, false, false, $chunk[8]); // Pass $textvar ($chunk[8]), but do OTLdata here + // so don't have to split OTLdata for each word + if ($k == 0) { + $letterwidth += $lbw; + } + if ($k == (count($letters) - 1)) { + $letterwidth += $rbw; + } + + // Warn user that maxwidth is insufficient + if ($letterwidth > $maxwidth + 0.0001) { + if ($letterwidth > $biggestword) { + $biggestword = $letterwidth; + } + $toonarrow = true; + } + } + } else { + // mPDF 6 + // Need to account for any XAdvance in GPOSinfo (OTLdata = $chunk[18]) + $wordXAdvance = []; + if (isset($chunk[18]) && $chunk[18]) { + preg_match_all('/(\xe2\x80\x8b| )/', $line, $spaces, PREG_OFFSET_CAPTURE); // U+200B Zero Width word boundary, or space + $lastoffset = 0; + $k = -1; // Added so that if no spaces found, "last word" later is calculated for the one and only word + foreach ($spaces[0] as $k => $m) { + $offset = $m[1]; + // ...TableCheckMinWidth... + // At this point, BIDI not applied, Writing direction is not set, and XAdvanceL balances XAdvanceR + for ($n = $lastoffset; $n < $offset; $n++) { + if (isset($chunk[18]['GPOSinfo'][$n]['XAdvanceL'])) { + if (isset($wordXAdvance[$k])) { + $wordXAdvance[$k] += $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; + } else { + $wordXAdvance[$k] = $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; + } + } + } + $lastoffset = $offset + 1; + } + + $k++; // last word + foreach ($chunk[18]['GPOSinfo'] as $n => $gpos) { + if ($n >= $lastoffset && isset($chunk[18]['GPOSinfo'][$n]['XAdvanceL'])) { + if (isset($wordXAdvance[$k])) { + $wordXAdvance[$k] += $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; + } else { + $wordXAdvance[$k] = $chunk[18]['GPOSinfo'][$n]['XAdvanceL']; + } + } + } + } + + $words = preg_split('/(\xe2\x80\x8b| )/', $line); // U+200B Zero Width word boundary, or space + foreach ($words as $k => $word) { + $word = trim($word); + $wordwidth = $this->GetStringWidth($word, false, false, $chunk[8]); // Pass $textvar ($chunk[8]), but do OTLdata here + // so don't have to split OTLdata for each word + if (isset($wordXAdvance[$k])) { + $wordwidth += ($wordXAdvance[$k] * 1000 / $this->CurrentFont['unitsPerEm']) * ($this->FontSize / 1000); + } + if ($k == 0) { + $wordwidth += $lbw; + } + if ($k == (count($words) - 1)) { + $wordwidth += $rbw; + } + + // mPDF 6 + if (count($words) == 1 && substr($chunk[0], 0, 1) != ' ') { + $acclength += $wordwidth; + } elseif (count($words) > 1 && $k == 0 && substr($chunk[0], 0, 1) != ' ') { + $acclength += $wordwidth; + } else { + $acclength = $wordwidth; + } + $acclongest = max($acclongest, $acclength); + if (count($words) == 1 && substr($chunk[0], -1, 1) == ' ') { + $acclength = 0; + } elseif (count($words) > 1 && ($k != (count($words) - 1) || substr($chunk[0], -1, 1) == ' ')) { + $acclength = 0; + } + + // Warn user that maxwidth is insufficient + if ($wordwidth > $maxwidth + 0.0001) { + if ($wordwidth > $biggestword) { + $biggestword = $wordwidth; + } + $toonarrow = true; + } + } + } + + // mPDF 6 Accumulated length of biggest word - across multiple chunks + if ($acclongest > $maxwidth + 0.0001) { + if ($acclongest > $biggestword) { + $biggestword = $acclongest; + } + $toonarrow = true; + } + + // RESET FONT SIZE/STYLE + // RESETTING VALUES + // Now we must deactivate what we have used + if (isset($chunk[2]) and $chunk[2] != '') { + $this->ResetStyles(); + } + if (isset($chunk[4]) and $chunk[4] != '') { + $this->SetFont($this->default_font, $this->FontStyle, 0, false); + } + if (isset($chunk[11]) and $chunk[11] != '') { + $this->SetFontSize($this->default_font_size, false); + } + $this->spanborddet = []; + $this->textvar = 0x00; // mPDF 5.7.1 + $this->OTLtags = []; + $this->lSpacingCSS = ''; + $this->wSpacingCSS = ''; + $this->fixedlSpacing = false; + $this->minwSpacing = 0; + } + + // Return -(wordsize) if word is bigger than maxwidth + // ADDED + if (($toonarrow) && ($this->table_error_report)) { + throw new \Mpdf\MpdfException("Word is too long to fit in table - " . $this->table_error_report_param); + } + if ($toonarrow) { + return -$biggestword; + } else { + return 1; + } + } + + function shrinkTable(&$table, $k) + { + $table['border_spacing_H'] /= $k; + $table['border_spacing_V'] /= $k; + + $table['padding']['T'] /= $k; + $table['padding']['R'] /= $k; + $table['padding']['B'] /= $k; + $table['padding']['L'] /= $k; + + $table['margin']['T'] /= $k; + $table['margin']['R'] /= $k; + $table['margin']['B'] /= $k; + $table['margin']['L'] /= $k; + + $table['border_details']['T']['w'] /= $k; + $table['border_details']['R']['w'] /= $k; + $table['border_details']['B']['w'] /= $k; + $table['border_details']['L']['w'] /= $k; + + if (isset($table['max_cell_border_width']['T'])) { + $table['max_cell_border_width']['T'] /= $k; + } + if (isset($table['max_cell_border_width']['R'])) { + $table['max_cell_border_width']['R'] /= $k; + } + if (isset($table['max_cell_border_width']['B'])) { + $table['max_cell_border_width']['B'] /= $k; + } + if (isset($table['max_cell_border_width']['L'])) { + $table['max_cell_border_width']['L'] /= $k; + } + + if ($this->simpleTables) { + $table['simple']['border_details']['T']['w'] /= $k; + $table['simple']['border_details']['R']['w'] /= $k; + $table['simple']['border_details']['B']['w'] /= $k; + $table['simple']['border_details']['L']['w'] /= $k; + } + + $table['miw'] /= $k; + $table['maw'] /= $k; + + for ($j = 0; $j < $table['nc']; $j++) { // columns + + $table['wc'][$j]['miw'] = isset($table['wc'][$j]['miw']) ? $table['wc'][$j]['miw'] : 0; + $table['wc'][$j]['maw'] = isset($table['wc'][$j]['maw']) ? $table['wc'][$j]['maw'] : 0; + + $table['wc'][$j]['miw'] /= $k; + $table['wc'][$j]['maw'] /= $k; + + if (isset($table['decimal_align'][$j]['maxs0']) && $table['decimal_align'][$j]['maxs0']) { + $table['decimal_align'][$j]['maxs0'] /= $k; + } + + if (isset($table['decimal_align'][$j]['maxs1']) && $table['decimal_align'][$j]['maxs1']) { + $table['decimal_align'][$j]['maxs1'] /= $k; + } + + if (isset($table['wc'][$j]['absmiw']) && $table['wc'][$j]['absmiw']) { + $table['wc'][$j]['absmiw'] /= $k; + } + + for ($i = 0; $i < $table['nr']; $i++) { // rows + + $c = &$table['cells'][$i][$j]; + + if (isset($c) && $c) { + + if (!$this->simpleTables) { + + if ($this->packTableData) { + + $cell = $this->_unpackCellBorder($c['borderbin']); + + $cell['border_details']['T']['w'] /= $k; + $cell['border_details']['R']['w'] /= $k; + $cell['border_details']['B']['w'] /= $k; + $cell['border_details']['L']['w'] /= $k; + $cell['border_details']['mbw']['TL'] /= $k; + $cell['border_details']['mbw']['TR'] /= $k; + $cell['border_details']['mbw']['BL'] /= $k; + $cell['border_details']['mbw']['BR'] /= $k; + $cell['border_details']['mbw']['LT'] /= $k; + $cell['border_details']['mbw']['LB'] /= $k; + $cell['border_details']['mbw']['RT'] /= $k; + $cell['border_details']['mbw']['RB'] /= $k; + + $c['borderbin'] = $this->_packCellBorder($cell); + + } else { + + $c['border_details']['T']['w'] /= $k; + $c['border_details']['R']['w'] /= $k; + $c['border_details']['B']['w'] /= $k; + $c['border_details']['L']['w'] /= $k; + $c['border_details']['mbw']['TL'] /= $k; + $c['border_details']['mbw']['TR'] /= $k; + $c['border_details']['mbw']['BL'] /= $k; + $c['border_details']['mbw']['BR'] /= $k; + $c['border_details']['mbw']['LT'] /= $k; + $c['border_details']['mbw']['LB'] /= $k; + $c['border_details']['mbw']['RT'] /= $k; + $c['border_details']['mbw']['RB'] /= $k; + } + } + + $c['padding']['T'] /= $k; + $c['padding']['R'] /= $k; + $c['padding']['B'] /= $k; + $c['padding']['L'] /= $k; + + $c['maxs'] = isset($c['maxs']) ? $c['maxs'] /= $k : null; + $c['w'] = isset($c['w']) ? $c['w'] /= $k : null; + + $c['s'] = isset($c['s']) ? $c['s'] /= $k : 0; + $c['h'] = isset($c['h']) ? $c['h'] /= $k : null; + + $c['miw'] = isset($c['miw']) ? $c['miw'] /= $k : 0; + $c['maw'] = isset($c['maw']) ? $c['maw'] /= $k : 0; + + $c['absmiw'] = isset($c['absmiw']) ? $c['absmiw'] /= $k : null; + + $c['nestedmaw'] = isset($c['nestedmaw']) ? $c['nestedmaw'] /= $k : null; + $c['nestedmiw'] = isset($c['nestedmiw']) ? $c['nestedmiw'] /= $k : null; + + if (isset($c['textbuffer'])) { + foreach ($c['textbuffer'] as $n => $tb) { + if (!empty($tb[16])) { + !isset($c['textbuffer'][$n][16]['T']) || $c['textbuffer'][$n][16]['T']['w'] /= $k; + !isset($c['textbuffer'][$n][16]['B']) || $c['textbuffer'][$n][16]['B']['w'] /= $k; + !isset($c['textbuffer'][$n][16]['L']) || $c['textbuffer'][$n][16]['L']['w'] /= $k; + !isset($c['textbuffer'][$n][16]['R']) || $c['textbuffer'][$n][16]['R']['w'] /= $k; + } + } + } + + unset($c); + } + + } // rows + } // columns + } + + function read_short(&$fh) + { + $s = fread($fh, 2); + $a = (ord($s[0]) << 8) + ord($s[1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + return $a; + } + + function _packCellBorder($cell) + { + if (!is_array($cell) || !isset($cell)) { + return ''; + } + + if (!$this->packTableData) { + return $cell; + } + // = 186 bytes + $bindata = pack("nnda6A10nnda6A10nnda6A10nnda6A10nd9", $cell['border'], $cell['border_details']['R']['s'], $cell['border_details']['R']['w'], $cell['border_details']['R']['c'], $cell['border_details']['R']['style'], $cell['border_details']['R']['dom'], $cell['border_details']['L']['s'], $cell['border_details']['L']['w'], $cell['border_details']['L']['c'], $cell['border_details']['L']['style'], $cell['border_details']['L']['dom'], $cell['border_details']['T']['s'], $cell['border_details']['T']['w'], $cell['border_details']['T']['c'], $cell['border_details']['T']['style'], $cell['border_details']['T']['dom'], $cell['border_details']['B']['s'], $cell['border_details']['B']['w'], $cell['border_details']['B']['c'], $cell['border_details']['B']['style'], $cell['border_details']['B']['dom'], $cell['border_details']['mbw']['BL'], $cell['border_details']['mbw']['BR'], $cell['border_details']['mbw']['RT'], $cell['border_details']['mbw']['RB'], $cell['border_details']['mbw']['TL'], $cell['border_details']['mbw']['TR'], $cell['border_details']['mbw']['LT'], $cell['border_details']['mbw']['LB'], (isset($cell['border_details']['cellposdom']) ? $cell['border_details']['cellposdom'] : 0)); + return $bindata; + } + + function _getBorderWidths($bindata) + { + if (!$bindata) { + return [0, 0, 0, 0]; + } + if (!$this->packTableData) { + return [$bindata['border_details']['T']['w'], $bindata['border_details']['R']['w'], $bindata['border_details']['B']['w'], $bindata['border_details']['L']['w']]; + } + + $bd = unpack("nbord/nrs/drw/a6rca/A10rst/nrd/nls/dlw/a6lca/A10lst/nld/nts/dtw/a6tca/A10tst/ntd/nbs/dbw/a6bca/A10bst/nbd/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd", $bindata); + $cell['border_details']['R']['w'] = $bd['rw']; + $cell['border_details']['L']['w'] = $bd['lw']; + $cell['border_details']['T']['w'] = $bd['tw']; + $cell['border_details']['B']['w'] = $bd['bw']; + return [$bd['tw'], $bd['rw'], $bd['bw'], $bd['lw']]; + } + + function _unpackCellBorder($bindata) + { + if (!$bindata) { + return []; + } + if (!$this->packTableData) { + return $bindata; + } + + $bd = unpack("nbord/nrs/drw/a6rca/A10rst/nrd/nls/dlw/a6lca/A10lst/nld/nts/dtw/a6tca/A10tst/ntd/nbs/dbw/a6bca/A10bst/nbd/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd", $bindata); + + $cell['border'] = $bd['bord']; + $cell['border_details']['R']['s'] = $bd['rs']; + $cell['border_details']['R']['w'] = $bd['rw']; + $cell['border_details']['R']['c'] = str_pad($bd['rca'], 6, "\x00"); + $cell['border_details']['R']['style'] = trim($bd['rst']); + $cell['border_details']['R']['dom'] = $bd['rd']; + + $cell['border_details']['L']['s'] = $bd['ls']; + $cell['border_details']['L']['w'] = $bd['lw']; + $cell['border_details']['L']['c'] = str_pad($bd['lca'], 6, "\x00"); + $cell['border_details']['L']['style'] = trim($bd['lst']); + $cell['border_details']['L']['dom'] = $bd['ld']; + + $cell['border_details']['T']['s'] = $bd['ts']; + $cell['border_details']['T']['w'] = $bd['tw']; + $cell['border_details']['T']['c'] = str_pad($bd['tca'], 6, "\x00"); + $cell['border_details']['T']['style'] = trim($bd['tst']); + $cell['border_details']['T']['dom'] = $bd['td']; + + $cell['border_details']['B']['s'] = $bd['bs']; + $cell['border_details']['B']['w'] = $bd['bw']; + $cell['border_details']['B']['c'] = str_pad($bd['bca'], 6, "\x00"); + $cell['border_details']['B']['style'] = trim($bd['bst']); + $cell['border_details']['B']['dom'] = $bd['bd']; + + $cell['border_details']['mbw']['BL'] = $bd['mbl']; + $cell['border_details']['mbw']['BR'] = $bd['mbr']; + $cell['border_details']['mbw']['RT'] = $bd['mrt']; + $cell['border_details']['mbw']['RB'] = $bd['mrb']; + $cell['border_details']['mbw']['TL'] = $bd['mtl']; + $cell['border_details']['mbw']['TR'] = $bd['mtr']; + $cell['border_details']['mbw']['LT'] = $bd['mlt']; + $cell['border_details']['mbw']['LB'] = $bd['mlb']; + $cell['border_details']['cellposdom'] = $bd['cpd']; + + + return($cell); + } + + ////////////////////////TABLE CODE (from PDFTable)///////////////////////////////////// + ////////////////////////TABLE CODE (from PDFTable)///////////////////////////////////// + ////////////////////////TABLE CODE (from PDFTable)///////////////////////////////////// + // table Array of (w, h, bc, nr, wc, hr, cells) + // w Width of table + // h Height of table + // nc Number column + // nr Number row + // hr List of height of each row + // wc List of width of each column + // cells List of cells of each rows, cells[i][j] is a cell in the table + function _tableColumnWidth(&$table, $firstpass = false) + { + $cs = &$table['cells']; + + $nc = $table['nc']; + $nr = $table['nr']; + $listspan = []; + + if ($table['borders_separate']) { + $tblbw = $table['border_details']['L']['w'] + $table['border_details']['R']['w'] + $table['margin']['L'] + $table['margin']['R'] + $table['padding']['L'] + $table['padding']['R'] + $table['border_spacing_H']; + } else { + $tblbw = $table['max_cell_border_width']['L'] / 2 + $table['max_cell_border_width']['R'] / 2 + $table['margin']['L'] + $table['margin']['R']; + } + + // ADDED table['l'][colno] + // = total length of text approx (using $c['s']) in that column - used to approximately distribute col widths in _tableWidth + // + for ($j = 0; $j < $nc; $j++) { // columns + $wc = &$table['wc'][$j]; + for ($i = 0; $i < $nr; $i++) { // rows + if (isset($cs[$i][$j]) && $cs[$i][$j]) { + $c = &$cs[$i][$j]; + + if ($this->simpleTables) { + if ($table['borders_separate']) { // NB twice border width + $extrcw = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H']; + } else { + $extrcw = $table['simple']['border_details']['L']['w'] / 2 + $table['simple']['border_details']['R']['w'] / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } else { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($c['borderbin']); + } else { + $br = $c['border_details']['R']['w']; + $bl = $c['border_details']['L']['w']; + } + if ($table['borders_separate']) { // NB twice border width + $extrcw = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H']; + } else { + $extrcw = $bl / 2 + $br / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } + + // $mw = $this->GetStringWidth('W') + $extrcw ; + $mw = $extrcw; // mPDF 6 + if (substr($c['a'], 0, 1) == 'D') { + $mw = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'] + $extrcw; + } + + $c['absmiw'] = $mw; + + if (isset($c['R']) && $c['R']) { + $c['maw'] = $c['miw'] = $this->FontSize + $extrcw; + if (isset($c['w'])) { // If cell width is specified + if ($c['miw'] < $c['w']) { + $c['miw'] = $c['w']; + } + } + if (!isset($c['colspan'])) { + if ($wc['miw'] < $c['miw']) { + $wc['miw'] = $c['miw']; + } + if ($wc['maw'] < $c['maw']) { + $wc['maw'] = $c['maw']; + } + + if ($firstpass) { + if (isset($table['l'][$j])) { + $table['l'][$j] += $c['miw']; + } else { + $table['l'][$j] = $c['miw']; + } + } + } + if ($c['miw'] > $wc['miw']) { + $wc['miw'] = $c['miw']; + } + if ($wc['miw'] > $wc['maw']) { + $wc['maw'] = $wc['miw']; + } + continue; + } + + if ($firstpass) { + if (isset($c['s'])) { + $c['s'] += $extrcw; + } + if (isset($c['maxs'])) { + $c['maxs'] += $extrcw; + } + if (isset($c['nestedmiw'])) { + $c['nestedmiw'] += $extrcw; + } + if (isset($c['nestedmaw'])) { + $c['nestedmaw'] += $extrcw; + } + } + + + // If minimum width has already been set by a nested table or inline object (image/form), use it + if (isset($c['nestedmiw']) && (!isset($this->table[1][1]['overflow']) || $this->table[1][1]['overflow'] != 'visible')) { + $miw = $c['nestedmiw']; + } else { + $miw = $mw; + } + + if (isset($c['maxs']) && $c['maxs'] != '') { + $c['s'] = $c['maxs']; + } + + // If maximum width has already been set by a nested table, use it + if (isset($c['nestedmaw'])) { + $c['maw'] = $c['nestedmaw']; + } else { + $c['maw'] = $c['s']; + } + + if (isset($table['overflow']) && $table['overflow'] == 'visible' && $table['level'] == 1) { + if (($c['maw'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) { + $c['maw'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw; + } + } + + if (isset($c['nowrap']) && $c['nowrap']) { + $miw = $c['maw']; + } + + if (isset($c['wpercent']) && $firstpass) { + if (isset($c['colspan'])) { // Not perfect - but % set on colspan is shared equally on cols. + for ($k = 0; $k < $c['colspan']; $k++) { + $table['wc'][($j + $k)]['wpercent'] = $c['wpercent'] / $c['colspan']; + } + } else { + if (isset($table['w']) && $table['w']) { + $c['w'] = $c['wpercent'] / 100 * ($table['w'] - $tblbw ); + } + $wc['wpercent'] = $c['wpercent']; + } + } + + if (isset($table['overflow']) && $table['overflow'] == 'visible' && $table['level'] == 1) { + if (isset($c['w']) && ($c['w'] + $tblbw) > $this->blk[$this->blklvl]['inner_width']) { + $c['w'] = $this->blk[$this->blklvl]['inner_width'] - $tblbw; + } + } + + + if (isset($c['w'])) { // If cell width is specified + if ($miw < $c['w']) { + $c['miw'] = $c['w']; + } // Cell min width = that specified + if ($miw > $c['w']) { + $c['miw'] = $c['w'] = $miw; + } // If width specified is less than minimum allowed (W) increase it + // mPDF 5.7.4 Do not set column width in colspan + // cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug + if (!isset($c['colspan'])) { + if (!isset($wc['w'])) { + $wc['w'] = 1; + } // If the Col width is not specified = set it to 1 + } + // mPDF 5.7.3 cf. http://www.mpdf1.com/forum/discussion/1648/nested-table-bug- + $c['maw'] = $c['w']; + } else { + $c['miw'] = $miw; + } // If cell width not specified -> set Cell min width it to minimum allowed (W) + + if (isset($c['miw']) && $c['maw'] < $c['miw']) { + $c['maw'] = $c['miw']; + } // If Cell max width < Minwidth - increase it to = + if (!isset($c['colspan'])) { + if (isset($c['miw']) && $wc['miw'] < $c['miw']) { + $wc['miw'] = $c['miw']; + } // Update Col Minimum and maximum widths + if ($wc['maw'] < $c['maw']) { + $wc['maw'] = $c['maw']; + } + if ((isset($wc['absmiw']) && $wc['absmiw'] < $c['absmiw']) || !isset($wc['absmiw'])) { + $wc['absmiw'] = $c['absmiw']; + } // Update Col Minimum and maximum widths + + if (isset($table['l'][$j])) { + $table['l'][$j] += $c['s']; + } else { + $table['l'][$j] = $c['s']; + } + } else { + $listspan[] = [$i, $j]; + } + + // Check if minimum width of the whole column is big enough for largest word to fit + // mPDF 6 + if (isset($c['textbuffer'])) { + if (isset($table['overflow']) && $table['overflow'] == 'wrap') { + $letter = true; + } // check for maximum width of letters + else { + $letter = false; + } + $minwidth = $this->TableCheckMinWidth($wc['miw'] - $extrcw, 0, $c['textbuffer'], $letter); + } else { + $minwidth = 0; + } + if ($minwidth < 0) { + // increase minimum width + if (!isset($c['colspan'])) { + $wc['miw'] = max((isset($wc['miw']) ? $wc['miw'] : 0), ((-$minwidth) + $extrcw)); + } else { + $c['miw'] = max((isset($c['miw']) ? $c['miw'] : 0), ((-$minwidth) + $extrcw)); + } + } + if (!isset($c['colspan'])) { + if ($wc['miw'] > $wc['maw']) { + $wc['maw'] = $wc['miw']; + } // update maximum width, if needed + } + } + unset($c); + }//rows + }//columns + // COLUMN SPANS + $wc = &$table['wc']; + foreach ($listspan as $span) { + list($i, $j) = $span; + $c = &$cs[$i][$j]; + $lc = $j + $c['colspan']; + if ($lc > $nc) { + $lc = $nc; + } + $wis = $wisa = 0; + $was = $wasa = 0; + $list = []; + for ($k = $j; $k < $lc; $k++) { + if (isset($table['l'][$k])) { + if ($c['R']) { + $table['l'][$k] += $c['miw'] / $c['colspan']; + } else { + $table['l'][$k] += $c['s'] / $c['colspan']; + } + } else { + if ($c['R']) { + $table['l'][$k] = $c['miw'] / $c['colspan']; + } else { + $table['l'][$k] = $c['s'] / $c['colspan']; + } + } + $wis += $wc[$k]['miw']; // $wis is the sum of the column miw in the colspan + $was += $wc[$k]['maw']; // $was is the sum of the column maw in the colspan + if (!isset($c['w'])) { + $list[] = $k; + $wisa += $wc[$k]['miw']; // $wisa is the sum of the column miw in cells with no width specified in the colspan + $wasa += $wc[$k]['maw']; // $wasa is the sum of the column maw in cells with no width specified in the colspan + } + } + if ($c['miw'] > $wis) { + if (!$wis) { + for ($k = $j; $k < $lc; $k++) { + $wc[$k]['miw'] = $c['miw'] / $c['colspan']; + } + } elseif (!count($list) && $wis != 0) { + $wi = $c['miw'] - $wis; + for ($k = $j; $k < $lc; $k++) { + $wc[$k]['miw'] += ($wc[$k]['miw'] / $wis) * $wi; + } + } else { + $wi = $c['miw'] - $wis; + // mPDF 5.7.2 Extra min width distributed proportionately to all cells in colspan without a specified width + // cf. http://www.mpdf1.com/forum/discussion/1607#Item_4 + foreach ($list as $k) { + if (!isset($wc[$k]['w']) || !$wc[$k]['w']) { + $wc[$k]['miw'] += ($wc[$k]['miw'] / $wisa) * $wi; + } + } // mPDF 5.7.2 + } + } + if ($c['maw'] > $was) { + if (!$wis) { + for ($k = $j; $k < $lc; $k++) { + $wc[$k]['maw'] = $c['maw'] / $c['colspan']; + } + } elseif (!count($list) && $was != 0) { + $wi = $c['maw'] - $was; + for ($k = $j; $k < $lc; $k++) { + $wc[$k]['maw'] += ($wc[$k]['maw'] / $was) * $wi; + } + } else { + $wi = $c['maw'] - $was; + // mPDF 5.7.4 Extra max width distributed evenly to all cells in colspan without a specified width + // cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug + foreach ($list as $k) { + $wc[$k]['maw'] += $wi / count($list); + } + } + } + unset($c); + } + + $checkminwidth = 0; + $checkmaxwidth = 0; + $totallength = 0; + + for ($i = 0; $i < $nc; $i++) { + $checkminwidth += $table['wc'][$i]['miw']; + $checkmaxwidth += $table['wc'][$i]['maw']; + $totallength += isset($table['l']) ? $table['l'][$i] : 0; + } + + if (!isset($table['w']) && $firstpass) { + $sumpc = 0; + $notset = 0; + for ($i = 0; $i < $nc; $i++) { + if (isset($table['wc'][$i]['wpercent']) && $table['wc'][$i]['wpercent']) { + $sumpc += $table['wc'][$i]['wpercent']; + } else { + $notset++; + } + } + + // If sum of widths as % >= 100% and not all columns are set + // Set a nominal width of 1% for unset columns + if ($sumpc >= 100 && $notset) { + for ($i = 0; $i < $nc; $i++) { + if ((!isset($table['wc'][$i]['wpercent']) || !$table['wc'][$i]['wpercent']) && + (!isset($table['wc'][$i]['w']) || !$table['wc'][$i]['w'])) { + $table['wc'][$i]['wpercent'] = 1; + } + } + } + + + if ($sumpc) { // if any percents are set + $sumnonpc = (100 - $sumpc); + $sumpc = max($sumpc, 100); + $miwleft = 0; + $miwleftcount = 0; + $miwsurplusnonpc = 0; + $maxcalcmiw = 0; + $mawleft = 0; + $mawleftcount = 0; + $mawsurplusnonpc = 0; + $maxcalcmaw = 0; + $mawnon = 0; + $miwnon = 0; + for ($i = 0; $i < $nc; $i++) { + if (isset($table['wc'][$i]['wpercent'])) { + $maxcalcmiw = max($maxcalcmiw, ($table['wc'][$i]['miw'] * $sumpc / $table['wc'][$i]['wpercent'])); + $maxcalcmaw = max($maxcalcmaw, ($table['wc'][$i]['maw'] * $sumpc / $table['wc'][$i]['wpercent'])); + } else { + $miwleft += $table['wc'][$i]['miw']; + $mawleft += $table['wc'][$i]['maw']; + if (!isset($table['wc'][$i]['w'])) { + $miwleftcount++; + $mawleftcount++; + } + } + } + if ($miwleft && $sumnonpc > 0) { + $miwnon = $miwleft * 100 / $sumnonpc; + } + if ($mawleft && $sumnonpc > 0) { + $mawnon = $mawleft * 100 / $sumnonpc; + } + if (($miwnon > $checkminwidth || $maxcalcmiw > $checkminwidth) && $this->keep_table_proportions) { + if ($miwnon > $maxcalcmiw) { + $miwsurplusnonpc = round((($miwnon * $sumnonpc / 100) - $miwleft), 3); + $checkminwidth = $miwnon; + } else { + $checkminwidth = $maxcalcmiw; + } + for ($i = 0; $i < $nc; $i++) { + if (isset($table['wc'][$i]['wpercent'])) { + $newmiw = $checkminwidth * $table['wc'][$i]['wpercent'] / 100; + if ($table['wc'][$i]['miw'] < $newmiw) { + $table['wc'][$i]['miw'] = $newmiw; + } + $table['wc'][$i]['w'] = 1; + } elseif ($miwsurplusnonpc && !$table['wc'][$i]['w']) { + $table['wc'][$i]['miw'] += $miwsurplusnonpc / $miwleftcount; + } + } + } + if (($mawnon > $checkmaxwidth || $maxcalcmaw > $checkmaxwidth)) { + if ($mawnon > $maxcalcmaw) { + $mawsurplusnonpc = round((($mawnon * $sumnonpc / 100) - $mawleft), 3); + $checkmaxwidth = $mawnon; + } else { + $checkmaxwidth = $maxcalcmaw; + } + for ($i = 0; $i < $nc; $i++) { + if (isset($table['wc'][$i]['wpercent'])) { + $newmaw = $checkmaxwidth * $table['wc'][$i]['wpercent'] / 100; + if ($table['wc'][$i]['maw'] < $newmaw) { + $table['wc'][$i]['maw'] = $newmaw; + } + $table['wc'][$i]['w'] = 1; + } elseif ($mawsurplusnonpc && !$table['wc'][$i]['w']) { + $table['wc'][$i]['maw'] += $mawsurplusnonpc / $mawleftcount; + } + if ($table['wc'][$i]['maw'] < $table['wc'][$i]['miw']) { + $table['wc'][$i]['maw'] = $table['wc'][$i]['miw']; + } + } + } + if ($checkminwidth > $checkmaxwidth) { + $checkmaxwidth = $checkminwidth; + } + } + } + + if (isset($table['wpercent']) && $table['wpercent']) { + $checkminwidth *= (100 / $table['wpercent']); + $checkmaxwidth *= (100 / $table['wpercent']); + } + + + $checkminwidth += $tblbw; + $checkmaxwidth += $tblbw; + + // Table['miw'] set by percent in first pass may be larger than sum of column miw + if ((isset($table['miw']) && $checkminwidth > $table['miw']) || !isset($table['miw'])) { + $table['miw'] = $checkminwidth; + } + if ((isset($table['maw']) && $checkmaxwidth > $table['maw']) || !isset($table['maw'])) { + $table['maw'] = $checkmaxwidth; + } + $table['tl'] = $totallength; + + // mPDF 6 + if ($this->table_rotate) { + $mxw = $this->tbrot_maxw; + } else { + $mxw = $this->blk[$this->blklvl]['inner_width']; + } + + if (!isset($table['overflow'])) { + $table['overflow'] = null; + } + + if ($table['overflow'] == 'visible') { + return [0, 0]; + } elseif ($table['overflow'] == 'hidden' && !$this->table_rotate && !$this->ColActive && $checkminwidth > $mxw) { + $table['w'] = $table['miw']; + return [0, 0]; + } + // elseif ($table['overflow']=='wrap') { return array(0,0); } // mPDF 6 + + if (isset($table['w']) && $table['w']) { + + if ($table['w'] >= $checkminwidth && $table['w'] <= $mxw) { + $table['maw'] = $mxw = $table['w']; + } elseif ($table['w'] >= $checkminwidth && $table['w'] > $mxw && $this->keep_table_proportions) { + $checkminwidth = $table['w']; + } elseif ($table['w'] < $checkminwidth && $checkminwidth < $mxw && $this->keep_table_proportions) { + $table['maw'] = $table['w'] = $checkminwidth; + } else { + unset($table['w']); + } + } + + $ratio = $checkminwidth / $mxw; + + if ($checkminwidth > $mxw) { + return [($ratio + 0.001), $checkminwidth]; // 0.001 to allow for rounded numbers when resizing + } + + unset($cs); + + return [0, 0]; + } + + function _tableWidth(&$table) + { + $widthcols = &$table['wc']; + $numcols = $table['nc']; + $tablewidth = 0; + + if ($table['borders_separate']) { + $tblbw = $table['border_details']['L']['w'] + $table['border_details']['R']['w'] + $table['margin']['L'] + $table['margin']['R'] + $table['padding']['L'] + $table['padding']['R'] + $table['border_spacing_H']; + } else { + $tblbw = $table['max_cell_border_width']['L'] / 2 + $table['max_cell_border_width']['R'] / 2 + $table['margin']['L'] + $table['margin']['R']; + } + + if ($table['level'] > 1 && isset($table['w'])) { + + if (isset($table['wpercent']) && $table['wpercent']) { + $table['w'] = $temppgwidth = (($table['w'] - $tblbw) * $table['wpercent'] / 100) + $tblbw; + } else { + $temppgwidth = $table['w']; + } + + } elseif ($this->table_rotate) { + + $temppgwidth = $this->tbrot_maxw; + + // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin) then allow for this + $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w']; + + if ($enddiv / $temppgwidth < 0.05) { + $temppgwidth -= $enddiv; + } + + } else { + + if (isset($table['w']) && $table['w'] < $this->blk[$this->blklvl]['inner_width']) { + $notfullwidth = 1; + $temppgwidth = $table['w']; + } elseif ($table['overflow'] == 'visible' && $table['level'] == 1) { + $temppgwidth = null; + } elseif ($table['overflow'] == 'hidden' && !$this->ColActive && isset($table['w']) && $table['w'] > $this->blk[$this->blklvl]['inner_width'] && $table['w'] == $table) { + // $temppgwidth = $this->blk[$this->blklvl]['inner_width']; + $temppgwidth = $table['w']; + } else { + $temppgwidth = $this->blk[$this->blklvl]['inner_width']; + } + + } + + $totaltextlength = 0; // Added - to sum $table['l'][colno] + $totalatextlength = 0; // Added - to sum $table['l'][colno] for those columns where width not set + $percentages_set = 0; + + for ($i = 0; $i < $numcols; $i++) { + if (isset($widthcols[$i]['wpercent'])) { + $tablewidth += $widthcols[$i]['maw']; + $percentages_set = 1; + } elseif (isset($widthcols[$i]['w'])) { + $tablewidth += $widthcols[$i]['miw']; + } else { + $tablewidth += $widthcols[$i]['maw']; + } + $totaltextlength += isset($table['l']) ? $table['l'][$i] : 0; + } + + if (!$totaltextlength) { + $totaltextlength = 1; + } + + $tablewidth += $tblbw; // Outer half of table borders + + if ($tablewidth > $temppgwidth) { + $table['w'] = $temppgwidth; + } elseif ($tablewidth < $temppgwidth && !isset($table['w']) && $percentages_set) { // if any widths set as percentages and max width fits < page width + $table['w'] = $table['maw']; + } + + // if table width is set and is > allowed width + if (isset($table['w']) && $table['w'] > $temppgwidth) { + $table['w'] = $temppgwidth; + } + + // IF the table width is now set - Need to distribute columns widths + // mPDF 5.7.3 + // If the table width is already set to the maximum width (e.g. nested table), then use maximum column widths exactly + if (isset($table['w']) && ($table['w'] == $tablewidth) && !$percentages_set) { + + // This sets the columns all to maximum width + for ($i = 0; $i < $numcols; $i++) { + $widthcols[$i] = $widthcols[$i]['maw']; + } + + } elseif (isset($table['w'])) { // elseif the table width is set distribute width using algorithm + + $wis = $wisa = 0; + $list = []; + $notsetlist = []; + + for ($i = 0; $i < $numcols; $i++) { + $wis += $widthcols[$i]['miw']; + if (!isset($widthcols[$i]['w']) || ($widthcols[$i]['w'] && $table['w'] > $temppgwidth && !$this->keep_table_proportions && !$notfullwidth )) { + $list[] = $i; + $wisa += $widthcols[$i]['miw']; + $totalatextlength += $table['l'][$i]; + } + } + + if (!$totalatextlength) { + $totalatextlength = 1; + } + + // Allocate spare (more than col's minimum width) across the cols according to their approx total text length + // Do it by setting minimum width here + if ($table['w'] > $wis + $tblbw) { + + // First set any cell widths set as percentages + if ($table['w'] < $temppgwidth || $this->keep_table_proportions) { + for ($k = 0; $k < $numcols; $k++) { + if (isset($widthcols[$k]['wpercent'])) { + $curr = $widthcols[$k]['miw']; + $widthcols[$k]['miw'] = ($table['w'] - $tblbw) * $widthcols[$k]['wpercent'] / 100; + $wis += $widthcols[$k]['miw'] - $curr; + $wisa += $widthcols[$k]['miw'] - $curr; + } + } + } + + // Now allocate surplus up to maximum width of each column + $surplus = 0; + $ttl = 0; // number of surplus columns + + if (!count($list)) { + + $wi = ($table['w'] - ($wis + $tblbw)); // i.e. extra space to distribute + + for ($k = 0; $k < $numcols; $k++) { + + $spareratio = ($table['l'][$k] / $totaltextlength); // gives ratio to divide up free space + + // Don't allocate more than Maximum required width - save rest in surplus + if ($widthcols[$k]['miw'] + ($wi * $spareratio) >= $widthcols[$k]['maw']) { // mPDF 5.7.3 + $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw'] - $widthcols[$k]['miw']); + $widthcols[$k]['miw'] = $widthcols[$k]['maw']; + } else { + $notsetlist[] = $k; + $ttl += $table['l'][$k]; + $widthcols[$k]['miw'] += ($wi * $spareratio); + } + } + + } else { + + $wi = ($table['w'] - ($wis + $tblbw)); // i.e. extra space to distribute + + foreach ($list as $k) { + + $spareratio = ($table['l'][$k] / $totalatextlength); // gives ratio to divide up free space + + // Don't allocate more than Maximum required width - save rest in surplus + if ($widthcols[$k]['miw'] + ($wi * $spareratio) >= $widthcols[$k]['maw']) { // mPDF 5.7.3 + $surplus += ($wi * $spareratio) - ($widthcols[$k]['maw'] - $widthcols[$k]['miw']); + $widthcols[$k]['miw'] = $widthcols[$k]['maw']; + } else { + $notsetlist[] = $k; + $ttl += $table['l'][$k]; + $widthcols[$k]['miw'] += ($wi * $spareratio); + } + } + } + + // If surplus still left over apportion it across columns + if ($surplus) { + + if (count($notsetlist) && count($notsetlist) < $numcols) { // if some are set only add to remaining - otherwise add to all of them + foreach ($notsetlist as $i) { + if ($ttl) { + $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl; + } + } + } elseif (count($list) && count($list) < $numcols) { // If some widths are defined, and others have been added up to their maxmum + foreach ($list as $i) { + $widthcols[$i]['miw'] += $surplus / count($list); + } + } elseif ($numcols) { // If all columns + $ttl = array_sum($table['l']); + if ($ttl) { + for ($i = 0; $i < $numcols; $i++) { + $widthcols[$i]['miw'] += $surplus * $table['l'][$i] / $ttl; + } + } + } + } + } + + // This sets the columns all to minimum width (which has been increased above if appropriate) + for ($i = 0; $i < $numcols; $i++) { + $widthcols[$i] = $widthcols[$i]['miw']; + } + + // TABLE NOT WIDE ENOUGH EVEN FOR MINIMUM CONTENT WIDTH + // If sum of column widths set are too wide for table + $checktablewidth = 0; + for ($i = 0; $i < $numcols; $i++) { + $checktablewidth += $widthcols[$i]; + } + + if ($checktablewidth > ($temppgwidth + 0.001 - $tblbw)) { + + $usedup = 0; + $numleft = 0; + + for ($i = 0; $i < $numcols; $i++) { + if ((isset($widthcols[$i]) && $widthcols[$i] > (($temppgwidth - $tblbw) / $numcols)) && (!isset($widthcols[$i]['w']))) { + $numleft++; + unset($widthcols[$i]); + } else { + $usedup += $widthcols[$i]; + } + } + + for ($i = 0; $i < $numcols; $i++) { + if (!isset($widthcols[$i]) || !$widthcols[$i]) { + $widthcols[$i] = ((($temppgwidth - $tblbw) - $usedup) / ($numleft)); + } + } + } + + } else { // table has no width defined + + $table['w'] = $tablewidth; + + for ($i = 0; $i < $numcols; $i++) { + + if (isset($widthcols[$i]['wpercent']) && $this->keep_table_proportions) { + $colwidth = $widthcols[$i]['maw']; + } elseif (isset($widthcols[$i]['w'])) { + $colwidth = $widthcols[$i]['miw']; + } else { + $colwidth = $widthcols[$i]['maw']; + } + + unset($widthcols[$i]); + $widthcols[$i] = $colwidth; + + } + } + + if ($table['overflow'] === 'visible' && $table['level'] == 1) { + + if ($tablewidth > $this->blk[$this->blklvl]['inner_width']) { + + for ($j = 0; $j < $numcols; $j++) { // columns + + for ($i = 0; $i < $table['nr']; $i++) { // rows + + if (isset($table['cells'][$i][$j]) && $table['cells'][$i][$j]) { + + $colspan = (isset($table['cells'][$i][$j]['colspan']) ? $table['cells'][$i][$j]['colspan'] : 1); + + if ($colspan > 1) { + $w = 0; + + for ($c = $j; $c < ($j + $colspan); $c++) { + $w += $widthcols[$c]; + } + + if ($w > $this->blk[$this->blklvl]['inner_width']) { + $diff = $w - ($this->blk[$this->blklvl]['inner_width'] - $tblbw); + for ($c = $j; $c < ($j + $colspan); $c++) { + $widthcols[$c] -= $diff * ($widthcols[$c] / $w); + } + $table['w'] -= $diff; + $table['csp'][$j] = $w - $diff; + } + } + } + } + } + } + + $pgNo = 0; + $currWc = 0; + + for ($i = 0; $i < $numcols; $i++) { // columns + + if (isset($table['csp'][$i])) { + $w = $table['csp'][$i]; + unset($table['csp'][$i]); + } else { + $w = $widthcols[$i]; + } + + if (($currWc + $w + $tblbw) > $this->blk[$this->blklvl]['inner_width']) { + $pgNo++; + $currWc = $widthcols[$i]; + } else { + $currWc += $widthcols[$i]; + } + + $table['colPg'][$i] = $pgNo; + } + } + } + + function _tableHeight(&$table) + { + $level = $table['level']; + $levelid = $table['levelid']; + $cells = &$table['cells']; + $numcols = $table['nc']; + $numrows = $table['nr']; + $listspan = []; + $checkmaxheight = 0; + $headerrowheight = 0; + $checkmaxheightplus = 0; + $headerrowheightplus = 0; + $firstrowheight = 0; + + $footerrowheight = 0; + $footerrowheightplus = 0; + if ($this->table_rotate) { + $temppgheight = $this->tbrot_maxh; + $remainingpage = $this->tbrot_maxh; + } else { + $temppgheight = ($this->h - $this->bMargin - $this->tMargin) - $this->kwt_height; + $remainingpage = ($this->h - $this->bMargin - $this->y) - $this->kwt_height; + + // If it is less than 1/20th of the remaining page height to finish the DIV (i.e. DIV padding + table bottom margin) + // then allow for this + $enddiv = $this->blk[$this->blklvl]['padding_bottom'] + $this->blk[$this->blklvl]['border_bottom']['w'] + $table['margin']['B']; + if ($remainingpage > $enddiv && $enddiv / $remainingpage < 0.05) { + $remainingpage -= $enddiv; + } elseif ($remainingpage == 0) { + $remainingpage = 0.001; + } + if ($temppgheight > $enddiv && $enddiv / $temppgheight < 0.05) { + $temppgheight -= $enddiv; + } elseif ($temppgheight == 0) { + $temppgheight = 0.001; + } + } + if ($remainingpage < 0) { + $remainingpage = 0.001; + } + if ($temppgheight < 0) { + $temppgheight = 0.001; + } + + for ($i = 0; $i < $numrows; $i++) { // rows + $heightrow = &$table['hr'][$i]; + for ($j = 0; $j < $numcols; $j++) { // columns + if (isset($cells[$i][$j]) && $cells[$i][$j]) { + $c = &$cells[$i][$j]; + + if ($this->simpleTables) { + if ($table['borders_separate']) { // NB twice border width + $extraWLR = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w']) + ($c['padding']['L'] + $c['padding']['R']) + $table['border_spacing_H']; + $extrh = ($table['simple']['border_details']['T']['w'] + $table['simple']['border_details']['B']['w']) + ($c['padding']['T'] + $c['padding']['B']) + $table['border_spacing_V']; + } else { + $extraWLR = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w']) / 2 + ($c['padding']['L'] + $c['padding']['R']); + $extrh = ($table['simple']['border_details']['T']['w'] + $table['simple']['border_details']['B']['w']) / 2 + ($c['padding']['T'] + $c['padding']['B']); + } + } else { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($c['borderbin']); + } else { + $bt = $c['border_details']['T']['w']; + $bb = $c['border_details']['B']['w']; + $br = $c['border_details']['R']['w']; + $bl = $c['border_details']['L']['w']; + } + if ($table['borders_separate']) { // NB twice border width + $extraWLR = $bl + $br + $c['padding']['L'] + $c['padding']['R'] + $table['border_spacing_H']; + $extrh = $bt + $bb + $c['padding']['T'] + $c['padding']['B'] + $table['border_spacing_V']; + } else { + $extraWLR = $bl / 2 + $br / 2 + $c['padding']['L'] + $c['padding']['R']; + $extrh = $bt / 2 + $bb / 2 + $c['padding']['T'] + $c['padding']['B']; + } + } + + if ($table['overflow'] == 'visible' && $level == 1) { + list($x, $cw) = $this->_splitTableGetWidth($table, $i, $j); + } else { + list($x, $cw) = $this->_tableGetWidth($table, $i, $j); + } + + + // Get CELL HEIGHT + // ++ extra parameter forces wrap to break word + if ($c['R'] && isset($c['textbuffer'])) { + $str = ''; + foreach ($c['textbuffer'] as $t) { + $str .= $t[0] . ' '; + } + $str = rtrim($str); + $s_fs = $this->FontSizePt; + $s_f = $this->FontFamily; + $s_st = $this->FontStyle; + $this->SetFont($c['textbuffer'][0][4], $c['textbuffer'][0][2], $c['textbuffer'][0][11] / $this->shrin_k, true, true); + $tempch = $this->GetStringWidth($str, true, $c['textbuffer'][0][18], $c['textbuffer'][0][8]); + if ($c['R'] >= 45 && $c['R'] < 90) { + $tempch = ((sin(deg2rad($c['R']))) * $tempch ) + ((sin(deg2rad($c['R']))) * (($c['textbuffer'][0][11] / Mpdf::SCALE) / $this->shrin_k)); + } + $this->SetFont($s_f, $s_st, $s_fs, true, true); + $ch = ($tempch ) + $extrh; + } else { + if (isset($c['textbuffer']) && !empty($c['textbuffer'])) { + $this->cellLineHeight = $c['cellLineHeight']; + $this->cellLineStackingStrategy = $c['cellLineStackingStrategy']; + $this->cellLineStackingShift = $c['cellLineStackingShift']; + $this->divwidth = $cw - $extraWLR; + $tempch = $this->printbuffer($c['textbuffer'], '', true, true); + } else { + $tempch = 0; + } + + // Added cellpadding top and bottom. (Lineheight already adjusted) + $ch = $tempch + $extrh; + } + // If height is defined and it is bigger than calculated $ch then update values + if (isset($c['h']) && $c['h'] > $ch) { + $c['mih'] = $ch; // in order to keep valign working + $ch = $c['h']; + } else { + $c['mih'] = $ch; + } + if (isset($c['rowspan'])) { + $listspan[] = [$i, $j]; + } elseif ($heightrow < $ch) { + $heightrow = $ch; + } + + // this is the extra used in _tableWrite to determine whether to trigger a page change + if ($table['borders_separate']) { + if ($i == ($numrows - 1) || (isset($c['rowspan']) && ($i + $c['rowspan']) == ($numrows))) { + $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + } else { + $extra = $table['border_spacing_V'] / 2; + } + } else { + if (!$this->simpleTables) { + $extra = $bb / 2; + } elseif ($this->simpleTables) { + $extra = $table['simple']['border_details']['B']['w'] / 2; + } + } + if (isset($table['is_thead'][$i]) && $table['is_thead'][$i]) { + if ($j == 0) { + $headerrowheight += $ch; + $headerrowheightplus += $ch + $extra; + } + } elseif (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) { + if ($j == 0) { + $footerrowheight += $ch; + $footerrowheightplus += $ch + $extra; + } + } else { + $checkmaxheight = max($checkmaxheight, $ch); + $checkmaxheightplus = max($checkmaxheightplus, $ch + $extra); + } + if ($this->tableLevel == 1 && $i == (isset($table['headernrows']) ? $table['headernrows'] : 0)) { + $firstrowheight = max($ch, $firstrowheight); + } + unset($c); + } + }//end of columns + }//end of rows + + $heightrow = &$table['hr']; + foreach ($listspan as $span) { + list($i, $j) = $span; + $c = &$cells[$i][$j]; + $lr = $i + $c['rowspan']; + if ($lr > $numrows) { + $lr = $numrows; + } + $hs = $hsa = 0; + $list = []; + for ($k = $i; $k < $lr; $k++) { + $hs += $heightrow[$k]; + // mPDF 6 + $sh = false; // specified height + for ($m = 0; $m < $numcols; $m++) { // columns + $tc = &$cells[$k][$m]; + if (isset($tc['rowspan'])) { + continue; + } + if (isset($tc['h'])) { + $sh = true; + break; + } + } + if (!$sh) { + $list[] = $k; + } + } + + if ($table['borders_separate']) { + if ($i == ($numrows - 1) || ($i + $c['rowspan']) == ($numrows)) { + $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + } else { + $extra = $table['border_spacing_V'] / 2; + } + } else { + if (!$this->simpleTables) { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($c['borderbin']); + } else { + $bb = $c['border_details']['B']['w']; + } + $extra = $bb / 2; + } elseif ($this->simpleTables) { + $extra = $table['simple']['border_details']['B']['w'] / 2; + } + } + if (!empty($table['is_thead'][$i])) { + $headerrowheight = max($headerrowheight, $hs); + $headerrowheightplus = max($headerrowheightplus, $hs + $extra); + } elseif (!empty($table['is_tfoot'][$i])) { + $footerrowheight = max($footerrowheight, $hs); + $footerrowheightplus = max($footerrowheightplus, $hs + $extra); + } else { + $checkmaxheight = max($checkmaxheight, $hs); + $checkmaxheightplus = max($checkmaxheightplus, $hs + $extra); + } + if ($this->tableLevel == 1 && $i == (isset($table['headernrows']) ? $table['headernrows'] : 0)) { + $firstrowheight = max($hs, $firstrowheight); + } + + if ($c['mih'] > $hs) { + if (!$hs) { + for ($k = $i; $k < $lr; $k++) { + $heightrow[$k] = $c['mih'] / $c['rowspan']; + } + } elseif (!count($list)) { // no rows in the rowspan have a height specified, so share amongst all rows equally + $hi = $c['mih'] - $hs; + for ($k = $i; $k < $lr; $k++) { + $heightrow[$k] += ($heightrow[$k] / $hs) * $hi; + } + } else { + $hi = $c['mih'] - $hs; // mPDF 6 + foreach ($list as $k) { + $heightrow[$k] += $hi / (count($list)); // mPDF 6 + } + } + } + unset($c); + + // If rowspans overlap so that one or more rows do not have a height set... + // i.e. for one or more rows, the only cells (explicit) in that row have rowspan>1 + // so heightrow is still == 0 + if ($heightrow[$i] == 0) { + // Get row extent to analyse above and below + $top = $i; + foreach ($listspan as $checkspan) { + list($cki, $ckj) = $checkspan; + $c = &$cells[$cki][$ckj]; + if (isset($c['rowspan']) && $c['rowspan'] > 1) { + if (($cki + $c['rowspan'] - 1) >= $i) { + $top = min($top, $cki); + } + } + } + $bottom = $i + $c['rowspan'] - 1; + // Check for overconstrained conditions + for ($k = $top; $k <= $bottom; $k++) { + // if ['hr'] for any of the others is also 0, then abort (too complicated) + if ($k != $i && $heightrow[$k] == 0) { + break(1); + } + // check again that top and bottom are not crossed by rowspans - or abort (too complicated) + if ($k == $top) { + // ???? take account of colspan as well??? + for ($m = 0; $m < $numcols; $m++) { // columns + if (!isset($cells[$k][$m]) || $cells[$k][$m] == 0) { + break(2); + } + } + } elseif ($k == $bottom) { + // ???? take account of colspan as well??? + for ($m = 0; $m < $numcols; $m++) { // columns + $c = &$cells[$k][$m]; + if (isset($c['rowspan']) && $c['rowspan'] > 1) { + break(2); + } + } + } + } + // By columns add up col height using ['h'] if set or ['mih'] if not + // Intentionally do not substract border-spacing + $colH = []; + $extH = 0; + $newhr = []; + for ($m = 0; $m < $numcols; $m++) { // columns + for ($k = $top; $k <= $bottom; $k++) { + if (isset($cells[$k][$m]) && $cells[$k][$m] != 0) { + $c = &$cells[$k][$m]; + if (isset($c['h']) && $c['h']) { + $useh = $c['h']; + } // ???? take account of colspan as well??? + else { + $useh = $c['mih']; + } + if (isset($colH[$m])) { + $colH[$m] += $useh; + } else { + $colH[$m] = $useh; + } + if (!isset($c['rowspan']) || $c['rowspan'] < 2) { + $newhr[$k] = max((isset($newhr[$k]) ? $newhr[$k] : 0), $useh); + } + } + } + $extH = max($extH, $colH[$m]); // mPDF 6 + } + $newhr[$i] = $extH - array_sum($newhr); + for ($k = $top; $k <= $bottom; $k++) { + $heightrow[$k] = $newhr[$k]; + } + } + + + unset($c); + } + + $table['h'] = array_sum($heightrow); + unset($heightrow); + + if ($table['borders_separate']) { + $table['h'] += $table['margin']['T'] + $table['margin']['B'] + $table['border_details']['T']['w'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] + $table['padding']['T'] + $table['padding']['B']; + } else { + $table['h'] += $table['margin']['T'] + $table['margin']['B'] + $table['max_cell_border_width']['T'] / 2 + $table['max_cell_border_width']['B'] / 2; + } + + $maxrowheight = $checkmaxheightplus + $headerrowheightplus + $footerrowheightplus; + $maxfirstrowheight = $firstrowheight + $headerrowheightplus + $footerrowheightplus; // includes thead, 1st row and tfoot + return [$table['h'], $maxrowheight, $temppgheight, $remainingpage, $maxfirstrowheight]; + } + + function _tableGetWidth(&$table, $i, $j) + { + $cell = &$table['cells'][$i][$j]; + if ($cell) { + if (isset($cell['x0'])) { + return [$cell['x0'], $cell['w0']]; + } + $x = 0; + $widthcols = &$table['wc']; + for ($k = 0; $k < $j; $k++) { + $x += $widthcols[$k]; + } + $w = $widthcols[$j]; + if (isset($cell['colspan'])) { + for ($k = $j + $cell['colspan'] - 1; $k > $j; $k--) { + $w += $widthcols[$k]; + } + } + $cell['x0'] = $x; + $cell['w0'] = $w; + return [$x, $w]; + } + return [0, 0]; + } + + function _splitTableGetWidth(&$table, $i, $j) + { + $cell = &$table['cells'][$i][$j]; + if ($cell) { + if (isset($cell['x0'])) { + return [$cell['x0'], $cell['w0']]; + } + $x = 0; + $widthcols = &$table['wc']; + $pg = $table['colPg'][$j]; + for ($k = 0; $k < $j; $k++) { + if ($table['colPg'][$k] == $pg) { + $x += $widthcols[$k]; + } + } + $w = $widthcols[$j]; + if (isset($cell['colspan'])) { + for ($k = $j + $cell['colspan'] - 1; $k > $j; $k--) { + if ($table['colPg'][$k] == $pg) { + $w += $widthcols[$k]; + } + } + } + $cell['x0'] = $x; + $cell['w0'] = $w; + return [$x, $w]; + } + return [0, 0]; + } + + function _tableGetHeight(&$table, $i, $j) + { + $cell = &$table['cells'][$i][$j]; + if ($cell) { + if (isset($cell['y0'])) { + return [$cell['y0'], $cell['h0']]; + } + $y = 0; + $heightrow = &$table['hr']; + for ($k = 0; $k < $i; $k++) { + $y += $heightrow[$k]; + } + $h = $heightrow[$i]; + if (isset($cell['rowspan'])) { + for ($k = $i + $cell['rowspan'] - 1; $k > $i; $k--) { + if (array_key_exists($k, $heightrow)) { + $h += $heightrow[$k]; + } else { + $this->logger->debug('Possible non-wellformed HTML markup in a table', ['context' => LogContext::HTML_MARKUP]); + } + } + } + $cell['y0'] = $y; + $cell['h0'] = $h; + return [$y, $h]; + } + return [0, 0]; + } + + function _tableGetMaxRowHeight($table, $row) + { + if ($row == $table['nc'] - 1) { + return $table['hr'][$row]; + } + $maxrowheight = $table['hr'][$row]; + for ($i = $row + 1; $i < $table['nr']; $i++) { + $cellsset = 0; + for ($j = 0; $j < $table['nc']; $j++) { + if (!empty($table['cells'][$i][$j])) { + if (isset($table['cells'][$i][$j]['colspan'])) { + $cellsset += $table['cells'][$i][$j]['colspan']; + } else { + $cellsset += 1; + } + } + } + if ($cellsset == $table['nc']) { + return $maxrowheight; + } else { + $maxrowheight += $table['hr'][$i]; + } + } + return $maxrowheight; + } + + // CHANGED TO ALLOW TABLE BORDER TO BE SPECIFIED CORRECTLY - added border_details + function _tableRect($x, $y, $w, $h, $bord = -1, $details = [], $buffer = false, $bSeparate = false, $cort = 'cell', $tablecorner = '', $bsv = 0, $bsh = 0) + { + $cellBorderOverlay = []; + + if ($bord == -1) { + $this->Rect($x, $y, $w, $h); + } elseif ($this->simpleTables && ($cort == 'cell')) { + $this->SetLineWidth($details['L']['w']); + if ($details['L']['c']) { + $this->SetDColor($details['L']['c']); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + $this->SetLineJoin(0); + $this->Rect($x, $y, $w, $h); + } elseif ($bord) { + if (!$bSeparate && $buffer) { + $priority = 'LRTB'; + for ($p = 0; $p < strlen($priority); $p++) { + $side = $priority[$p]; + $details['p'] = $side; + + $dom = 0; + if (isset($details[$side]['w'])) { + $dom += ($details[$side]['w'] * 100000); + } + if (isset($details[$side]['style'])) { + $dom += (array_search($details[$side]['style'], $this->borderstyles) * 100); + } + if (isset($details[$side]['dom'])) { + $dom += ($details[$side]['dom'] * 10); + } + + // Precedence to darker colours at joins + $coldom = 0; + if (isset($details[$side]['c']) && is_array($details[$side]['c'])) { + if ($details[$side]['c'][0] == 3) { // RGB + $coldom = 10 - (((ord($details[$side]['c'][1]) * 1.00) + (ord($details[$side]['c'][2]) * 1.00) + (ord($details[$side]['c'][3]) * 1.00)) / 76.5); + } + } // 10 black - 0 white + if ($coldom) { + $dom += $coldom; + } + // Lastly precedence to RIGHT and BOTTOM cells at joins + if (isset($details['cellposdom'])) { + $dom += $details['cellposdom']; + } + + $save = false; + if ($side == 'T' && $this->issetBorder($bord, Border::TOP)) { + $cbord = Border::TOP; + $save = true; + } elseif ($side == 'L' && $this->issetBorder($bord, Border::LEFT)) { + $cbord = Border::LEFT; + $save = true; + } elseif ($side == 'R' && $this->issetBorder($bord, Border::RIGHT)) { + $cbord = Border::RIGHT; + $save = true; + } elseif ($side == 'B' && $this->issetBorder($bord, Border::BOTTOM)) { + $cbord = Border::BOTTOM; + $save = true; + } + + if ($save) { + $this->cellBorderBuffer[] = pack("A16nCnda6A10d14", str_pad(sprintf("%08.7f", $dom), 16, "0", STR_PAD_LEFT), $cbord, ord($side), $details[$side]['s'], $details[$side]['w'], $details[$side]['c'], $details[$side]['style'], $x, $y, $w, $h, $details['mbw']['BL'], $details['mbw']['BR'], $details['mbw']['RT'], $details['mbw']['RB'], $details['mbw']['TL'], $details['mbw']['TR'], $details['mbw']['LT'], $details['mbw']['LB'], $details['cellposdom'], 0); + if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset' || $details[$side]['style'] == 'double') { + $details[$side]['overlay'] = true; + $this->cellBorderBuffer[] = pack("A16nCnda6A10d14", str_pad(sprintf("%08.7f", ($dom + 4)), 16, "0", STR_PAD_LEFT), $cbord, ord($side), $details[$side]['s'], $details[$side]['w'], $details[$side]['c'], $details[$side]['style'], $x, $y, $w, $h, $details['mbw']['BL'], $details['mbw']['BR'], $details['mbw']['RT'], $details['mbw']['RB'], $details['mbw']['TL'], $details['mbw']['TR'], $details['mbw']['LT'], $details['mbw']['LB'], $details['cellposdom'], 1); + } + } + } + return; + } + + if (isset($details['p']) && strlen($details['p']) > 1) { + $priority = $details['p']; + } else { + $priority = 'LTRB'; + } + $Tw = 0; + $Rw = 0; + $Bw = 0; + $Lw = 0; + if (isset($details['T']['w'])) { + $Tw = $details['T']['w']; + } + if (isset($details['R']['w'])) { + $Rw = $details['R']['w']; + } + if (isset($details['B']['w'])) { + $Bw = $details['B']['w']; + } + if (isset($details['L']['w'])) { + $Lw = $details['L']['w']; + } + + $x2 = $x + $w; + $y2 = $y + $h; + $oldlinewidth = $this->LineWidth; + + for ($p = 0; $p < strlen($priority); $p++) { + $side = $priority[$p]; + $xadj = 0; + $xadj2 = 0; + $yadj = 0; + $yadj2 = 0; + $print = false; + if ($Tw && $side == 'T' && $this->issetBorder($bord, Border::TOP)) { // TOP + $ly1 = $y; + $ly2 = $y; + $lx1 = $x; + $lx2 = $x2; + $this->SetLineWidth($Tw); + if ($cort == 'cell' || strpos($tablecorner, 'L') !== false) { + if ($Tw > $Lw) { + $xadj = ($Tw - $Lw) / 2; + } + if ($Tw < $Lw) { + $xadj = ($Tw + $Lw) / 2; + } + } else { + $xadj = $Tw / 2 - $bsh / 2; + } + if ($cort == 'cell' || strpos($tablecorner, 'R') !== false) { + if ($Tw > $Rw) { + $xadj2 = ($Tw - $Rw) / 2; + } + if ($Tw < $Rw) { + $xadj2 = ($Tw + $Rw) / 2; + } + } else { + $xadj2 = $Tw / 2 - $bsh / 2; + } + if (!$bSeparate && !empty($details['mbw']) && !empty($details['mbw']['TL'])) { + $xadj = ($Tw - $details['mbw']['TL']) / 2; + } + if (!$bSeparate && !empty($details['mbw']) && !empty($details['mbw']['TR'])) { + $xadj2 = ($Tw - $details['mbw']['TR']) / 2; + } + $print = true; + } + if ($Lw && $side == 'L' && $this->issetBorder($bord, Border::LEFT)) { // LEFT + $ly1 = $y; + $ly2 = $y2; + $lx1 = $x; + $lx2 = $x; + $this->SetLineWidth($Lw); + if ($cort == 'cell' || strpos($tablecorner, 'T') !== false) { + if ($Lw > $Tw) { + $yadj = ($Lw - $Tw) / 2; + } + if ($Lw < $Tw) { + $yadj = ($Lw + $Tw) / 2; + } + } else { + $yadj = $Lw / 2 - $bsv / 2; + } + if ($cort == 'cell' || strpos($tablecorner, 'B') !== false) { + if ($Lw > $Bw) { + $yadj2 = ($Lw - $Bw) / 2; + } + if ($Lw < $Bw) { + $yadj2 = ($Lw + $Bw) / 2; + } + } else { + $yadj2 = $Lw / 2 - $bsv / 2; + } + if (!$bSeparate && $details['mbw']['LT']) { + $yadj = ($Lw - $details['mbw']['LT']) / 2; + } + if (!$bSeparate && $details['mbw']['LB']) { + $yadj2 = ($Lw - $details['mbw']['LB']) / 2; + } + $print = true; + } + if ($Rw && $side == 'R' && $this->issetBorder($bord, Border::RIGHT)) { // RIGHT + $ly1 = $y; + $ly2 = $y2; + $lx1 = $x2; + $lx2 = $x2; + $this->SetLineWidth($Rw); + if ($cort == 'cell' || strpos($tablecorner, 'T') !== false) { + if ($Rw < $Tw) { + $yadj = ($Rw + $Tw) / 2; + } + if ($Rw > $Tw) { + $yadj = ($Rw - $Tw) / 2; + } + } else { + $yadj = $Rw / 2 - $bsv / 2; + } + + if ($cort == 'cell' || strpos($tablecorner, 'B') !== false) { + if ($Rw > $Bw) { + $yadj2 = ($Rw - $Bw) / 2; + } + if ($Rw < $Bw) { + $yadj2 = ($Rw + $Bw) / 2; + } + } else { + $yadj2 = $Rw / 2 - $bsv / 2; + } + + if (!$bSeparate && !empty($details['mbw']) && !empty($details['mbw']['RT'])) { + $yadj = ($Rw - $details['mbw']['RT']) / 2; + } + if (!$bSeparate && !empty($details['mbw']) && !empty($details['mbw']['RB'])) { + $yadj2 = ($Rw - $details['mbw']['RB']) / 2; + } + $print = true; + } + if ($Bw && $side == 'B' && $this->issetBorder($bord, Border::BOTTOM)) { // BOTTOM + $ly1 = $y2; + $ly2 = $y2; + $lx1 = $x; + $lx2 = $x2; + $this->SetLineWidth($Bw); + if ($cort == 'cell' || strpos($tablecorner, 'L') !== false) { + if ($Bw > $Lw) { + $xadj = ($Bw - $Lw) / 2; + } + if ($Bw < $Lw) { + $xadj = ($Bw + $Lw) / 2; + } + } else { + $xadj = $Bw / 2 - $bsh / 2; + } + if ($cort == 'cell' || strpos($tablecorner, 'R') !== false) { + if ($Bw > $Rw) { + $xadj2 = ($Bw - $Rw) / 2; + } + if ($Bw < $Rw) { + $xadj2 = ($Bw + $Rw) / 2; + } + } else { + $xadj2 = $Bw / 2 - $bsh / 2; + } + if (!$bSeparate && isset($details['mbw']) && isset($details['mbw']['BL'])) { + $xadj = ($Bw - $details['mbw']['BL']) / 2; + } + if (!$bSeparate && isset($details['mbw']) && isset($details['mbw']['BR'])) { + $xadj2 = ($Bw - $details['mbw']['BR']) / 2; + } + $print = true; + } + + // Now draw line + if ($print) { + /* -- TABLES-ADVANCED-BORDERS -- */ + if ($details[$side]['style'] == 'double') { + if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) { + if ($details[$side]['c']) { + $this->SetDColor($details[$side]['c']); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2); + } + if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) { + if ($bSeparate && $cort == 'table') { + if ($side == 'T') { + $xadj -= $this->LineWidth / 2; + $xadj2 -= $this->LineWidth; + if ($this->issetBorder($bord, Border::LEFT)) { + $xadj += $this->LineWidth / 2; + } + if ($this->issetBorder($bord, Border::RIGHT)) { + $xadj2 += $this->LineWidth; + } + } + if ($side == 'L') { + $yadj -= $this->LineWidth / 2; + $yadj2 -= $this->LineWidth; + if ($this->issetBorder($bord, Border::TOP)) { + $yadj += $this->LineWidth / 2; + } + if ($this->issetBorder($bord, Border::BOTTOM)) { + $yadj2 += $this->LineWidth; + } + } + if ($side == 'B') { + $xadj -= $this->LineWidth / 2; + $xadj2 -= $this->LineWidth; + if ($this->issetBorder($bord, Border::LEFT)) { + $xadj += $this->LineWidth / 2; + } + if ($this->issetBorder($bord, Border::RIGHT)) { + $xadj2 += $this->LineWidth; + } + } + if ($side == 'R') { + $yadj -= $this->LineWidth / 2; + $yadj2 -= $this->LineWidth; + if ($this->issetBorder($bord, Border::TOP)) { + $yadj += $this->LineWidth / 2; + } + if ($this->issetBorder($bord, Border::BOTTOM)) { + $yadj2 += $this->LineWidth; + } + } + } + + $this->SetLineWidth($this->LineWidth / 3); + + $tbcol = $this->colorConverter->convert(255, $this->PDFAXwarnings); + for ($l = 0; $l <= $this->blklvl; $l++) { + if ($this->blk[$l]['bgcolor']) { + $tbcol = ($this->blk[$l]['bgcolorarray']); + } + } + + if ($bSeparate) { + $cellBorderOverlay[] = [ + 'x' => $lx1 + $xadj, + 'y' => $ly1 + $yadj, + 'x2' => $lx2 - $xadj2, + 'y2' => $ly2 - $yadj2, + 'col' => $tbcol, + 'lw' => $this->LineWidth, + ]; + } else { + $this->SetDColor($tbcol); + $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2); + } + } + } elseif (isset($details[$side]['style']) && ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'groove' || $details[$side]['style'] == 'inset' || $details[$side]['style'] == 'outset')) { + if (!isset($details[$side]['overlay']) || !$details[$side]['overlay'] || $bSeparate) { + if ($details[$side]['c']) { + $this->SetDColor($details[$side]['c']); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + if ($details[$side]['style'] == 'outset' || $details[$side]['style'] == 'groove') { + $nc = $this->colorConverter->darken($details[$side]['c']); + $this->SetDColor($nc); + } elseif ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') { + $nc = $this->colorConverter->lighten($details[$side]['c']); + $this->SetDColor($nc); + } + $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2); + } + if ((isset($details[$side]['overlay']) && $details[$side]['overlay']) || $bSeparate) { + if ($details[$side]['c']) { + $this->SetDColor($details[$side]['c']); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + $doubleadj = ($this->LineWidth) / 3; + $this->SetLineWidth($this->LineWidth / 2); + $xadj3 = $yadj3 = $wadj3 = $hadj3 = 0; + + if ($details[$side]['style'] == 'ridge' || $details[$side]['style'] == 'inset') { + $nc = $this->colorConverter->darken($details[$side]['c']); + + if ($bSeparate && $cort == 'table') { + if ($side == 'T') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = -$this->LineWidth / 2; + $wadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::LEFT)) { + $xadj3 += $this->LineWidth; + $wadj3 -= $this->LineWidth; + } + if ($this->issetBorder($bord, Border::RIGHT)) { + $wadj3 -= $this->LineWidth * 2; + } + } + if ($side == 'L') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = -$this->LineWidth / 2; + $hadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::TOP)) { + $yadj3 += $this->LineWidth; + $hadj3 -= $this->LineWidth; + } + if ($this->issetBorder($bord, Border::BOTTOM)) { + $hadj3 -= $this->LineWidth * 2; + } + } + if ($side == 'B') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = -$this->LineWidth / 2; + $wadj3 = $this->LineWidth; + } + if ($side == 'R') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = -$this->LineWidth / 2; + $hadj3 = $this->LineWidth; + } + } elseif ($side == 'T') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = $this->LineWidth / 2; + $wadj3 = -$this->LineWidth * 2; + } elseif ($side == 'L') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = $this->LineWidth / 2; + $hadj3 = -$this->LineWidth * 2; + } elseif ($side == 'B' && $bSeparate) { + $yadj3 = $this->LineWidth / 2; + $wadj3 = $this->LineWidth / 2; + } elseif ($side == 'R' && $bSeparate) { + $xadj3 = $this->LineWidth / 2; + $hadj3 = $this->LineWidth / 2; + } elseif ($side == 'B') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = $this->LineWidth / 2; + } elseif ($side == 'R') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = $this->LineWidth / 2; + } + } else { + $nc = $this->colorConverter->lighten($details[$side]['c']); + + if ($bSeparate && $cort == 'table') { + if ($side == 'T') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = -$this->LineWidth / 2; + $wadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::LEFT)) { + $xadj3 += $this->LineWidth; + $wadj3 -= $this->LineWidth; + } + } + if ($side == 'L') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = -$this->LineWidth / 2; + $hadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::TOP)) { + $yadj3 += $this->LineWidth; + $hadj3 -= $this->LineWidth; + } + } + if ($side == 'B') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = -$this->LineWidth / 2; + $wadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::LEFT)) { + $xadj3 += $this->LineWidth; + $wadj3 -= $this->LineWidth; + } + } + if ($side == 'R') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = -$this->LineWidth / 2; + $hadj3 = $this->LineWidth; + if ($this->issetBorder($bord, Border::TOP)) { + $yadj3 += $this->LineWidth; + $hadj3 -= $this->LineWidth; + } + } + } elseif ($side == 'T') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = $this->LineWidth / 2; + } elseif ($side == 'L') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = $this->LineWidth / 2; + } elseif ($side == 'B' && $bSeparate) { + $yadj3 = $this->LineWidth / 2; + $xadj3 = $this->LineWidth / 2; + } elseif ($side == 'R' && $bSeparate) { + $xadj3 = $this->LineWidth / 2; + $yadj3 = $this->LineWidth / 2; + } elseif ($side == 'B') { + $yadj3 = $this->LineWidth / 2; + $xadj3 = -$this->LineWidth / 2; + $wadj3 = $this->LineWidth; + } elseif ($side == 'R') { + $xadj3 = $this->LineWidth / 2; + $yadj3 = -$this->LineWidth / 2; + $hadj3 = $this->LineWidth; + } + } + + if ($bSeparate) { + $cellBorderOverlay[] = [ + 'x' => $lx1 + $xadj + $xadj3, + 'y' => $ly1 + $yadj + $yadj3, + 'x2' => $lx2 - $xadj2 + $xadj3 + $wadj3, + 'y2' => $ly2 - $yadj2 + $yadj3 + $hadj3, + 'col' => $nc, + 'lw' => $this->LineWidth, + ]; + } else { + $this->SetDColor($nc); + $this->Line($lx1 + $xadj + $xadj3, $ly1 + $yadj + $yadj3, $lx2 - $xadj2 + $xadj3 + $wadj3, $ly2 - $yadj2 + $yadj3 + $hadj3); + } + } + } else { + /* -- END TABLES-ADVANCED-BORDERS -- */ + if ($details[$side]['style'] == 'dashed') { + $dashsize = 2; // final dash will be this + 1*linewidth + $dashsizek = 1.5; // ratio of Dash/Blank + $this->SetDash($dashsize, ($dashsize / $dashsizek) + ($this->LineWidth * 2)); + } elseif ($details[$side]['style'] == 'dotted') { + $this->SetLineJoin(1); + $this->SetLineCap(1); + $this->SetDash(0.001, ($this->LineWidth * 2)); + } + if ($details[$side]['c']) { + $this->SetDColor($details[$side]['c']); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + $this->Line($lx1 + $xadj, $ly1 + $yadj, $lx2 - $xadj2, $ly2 - $yadj2); + /* -- TABLES-ADVANCED-BORDERS -- */ + } + /* -- END TABLES-ADVANCED-BORDERS -- */ + + // Reset Corners + $this->SetDash(); + // BUTT style line cap + $this->SetLineCap(2); + } + } + + if ($bSeparate && count($cellBorderOverlay)) { + foreach ($cellBorderOverlay as $cbo) { + $this->SetLineWidth($cbo['lw']); + $this->SetDColor($cbo['col']); + $this->Line($cbo['x'], $cbo['y'], $cbo['x2'], $cbo['y2']); + } + } + + // $this->SetLineWidth($oldlinewidth); + // $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + } + + /* -- TABLES -- */ + /* -- TABLES-ADVANCED-BORDERS -- */ + + /* -- END TABLES-ADVANCED-BORDERS -- */ + + function setBorder(&$var, $flag, $set = true) + { + $flag = intval($flag); + if ($set) { + $set = true; + } + $var = intval($var); + $var = $set ? ($var | $flag) : ($var & ~$flag); + } + + function issetBorder($var, $flag) + { + $flag = intval($flag); + $var = intval($var); + return (($var & $flag) == $flag); + } + + function _table2cellBorder(&$tableb, &$cbdb, &$cellb, $bval) + { + if ($tableb && $tableb['w'] > $cbdb['w']) { + $cbdb = $tableb; + $this->setBorder($cellb, $bval); + } elseif ($tableb && $tableb['w'] == $cbdb['w'] && array_search($tableb['style'], $this->borderstyles) > array_search($cbdb['style'], $this->borderstyles)) { + $cbdb = $tableb; + $this->setBorder($cellb, $bval); + } + } + + // FIX BORDERS ******************************************** + function _fixTableBorders(&$table) + { + if (!$table['borders_separate'] && $table['border_details']['L']['w']) { + $table['max_cell_border_width']['L'] = $table['border_details']['L']['w']; + } + if (!$table['borders_separate'] && $table['border_details']['R']['w']) { + $table['max_cell_border_width']['R'] = $table['border_details']['R']['w']; + } + if (!$table['borders_separate'] && $table['border_details']['T']['w']) { + $table['max_cell_border_width']['T'] = $table['border_details']['T']['w']; + } + if (!$table['borders_separate'] && $table['border_details']['B']['w']) { + $table['max_cell_border_width']['B'] = $table['border_details']['B']['w']; + } + if ($this->simpleTables) { + return; + } + $cells = &$table['cells']; + $numcols = $table['nc']; + $numrows = $table['nr']; + /* -- TABLES-ADVANCED-BORDERS -- */ + if (isset($table['topntail']) && $table['topntail']) { + $tntborddet = $this->border_details($table['topntail']); + } + if (isset($table['thead-underline']) && $table['thead-underline']) { + $thuborddet = $this->border_details($table['thead-underline']); + } + /* -- END TABLES-ADVANCED-BORDERS -- */ + + for ($i = 0; $i < $numrows; $i++) { // Rows + for ($j = 0; $j < $numcols; $j++) { // Columns + if (isset($cells[$i][$j]) && $cells[$i][$j]) { + $cell = &$cells[$i][$j]; + if ($this->packTableData) { + $cbord = $this->_unpackCellBorder($cell['borderbin']); + } else { + $cbord = &$cells[$i][$j]; + } + + // mPDF 5.7.3 + if (!$cbord['border'] && $cbord['border'] !== 0 && isset($table['border']) && $table['border'] && $this->table_border_attr_set) { + $cbord['border'] = $table['border']; + $cbord['border_details'] = $table['border_details']; + } + + if (isset($cell['colspan']) && $cell['colspan'] > 1) { + $ccolsp = $cell['colspan']; + } else { + $ccolsp = 1; + } + if (isset($cell['rowspan']) && $cell['rowspan'] > 1) { + $crowsp = $cell['rowspan']; + } else { + $crowsp = 1; + } + + $cbord['border_details']['cellposdom'] = ((($i + 1) / $numrows) / 10000 ) + ((($j + 1) / $numcols) / 10 ); + // Inherit Cell border from Table border + if ($this->table_border_css_set && !$table['borders_separate']) { + if ($i == 0) { + $this->_table2cellBorder($table['border_details']['T'], $cbord['border_details']['T'], $cbord['border'], Border::TOP); + } + if ($i == ($numrows - 1) || ($i + $crowsp) == ($numrows)) { + $this->_table2cellBorder($table['border_details']['B'], $cbord['border_details']['B'], $cbord['border'], Border::BOTTOM); + } + if ($j == 0) { + $this->_table2cellBorder($table['border_details']['L'], $cbord['border_details']['L'], $cbord['border'], Border::LEFT); + } + if ($j == ($numcols - 1) || ($j + $ccolsp) == ($numcols)) { + $this->_table2cellBorder($table['border_details']['R'], $cbord['border_details']['R'], $cbord['border'], Border::RIGHT); + } + } + + /* -- TABLES-ADVANCED-BORDERS -- */ + $fixbottom = true; + if (isset($table['topntail']) && $table['topntail']) { + if ($i == 0) { + $cbord['border_details']['T'] = $tntborddet; + $this->setBorder($cbord['border'], Border::TOP); + } + if ($this->tableLevel == 1 && $table['headernrows'] > 0 && $i == $table['headernrows'] - 1) { + $cbord['border_details']['B'] = $tntborddet; + $this->setBorder($cbord['border'], Border::BOTTOM); + $fixbottom = false; + } elseif ($this->tableLevel == 1 && $table['headernrows'] > 0 && $i == $table['headernrows']) { + if (!$table['borders_separate']) { + $cbord['border_details']['T'] = $tntborddet; + $this->setBorder($cbord['border'], Border::TOP); + } + } + if ($this->tableLevel == 1 && $table['footernrows'] > 0 && $i == ($numrows - $table['footernrows'] - 1)) { + if (!$table['borders_separate']) { + $cbord['border_details']['B'] = $tntborddet; + $this->setBorder($cbord['border'], Border::BOTTOM); + $fixbottom = false; + } + } elseif ($this->tableLevel == 1 && $table['footernrows'] > 0 && $i == ($numrows - $table['footernrows'])) { + $cbord['border_details']['T'] = $tntborddet; + $this->setBorder($cbord['border'], Border::TOP); + } + if ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader + if (!$table['borders_separate']) { + $cbord['border_details']['T'] = $tntborddet; + $this->setBorder($cbord['border'], Border::TOP); + } + } + if ($i == ($numrows - 1) || ($i + $crowsp) == ($numrows)) { + $cbord['border_details']['B'] = $tntborddet; + $this->setBorder($cbord['border'], Border::BOTTOM); + } + } + if (isset($table['thead-underline']) && $table['thead-underline']) { + if ($table['borders_separate']) { + if ($i == 0) { + $cbord['border_details']['B'] = $thuborddet; + $this->setBorder($cbord['border'], Border::BOTTOM); + $fixbottom = false; + } + } else { + if ($this->tableLevel == 1 && $table['headernrows'] > 0 && $i == $table['headernrows'] - 1) { + $cbord['border_details']['T'] = $thuborddet; + $this->setBorder($cbord['border'], Border::TOP); + } elseif ($this->tabletheadjustfinished) { // $this->tabletheadjustfinished called from tableheader + $cbord['border_details']['T'] = $thuborddet; + $this->setBorder($cbord['border'], Border::TOP); + } + } + } + + // Collapse Border - Algorithm for conflicting borders + // Hidden >> Width >> double>solid>dashed>dotted... >> style set on cell>table >> top/left>bottom/right + // Do not turn off border which is overridden + // Needed for page break for TOP/BOTTOM both to be defined in Collapsed borders + // Means it is painted twice. (Left/Right can still disable overridden border) + if (!$table['borders_separate']) { + + if (($i < ($numrows - 1) || ($i + $crowsp) < $numrows ) && $fixbottom) { // Bottom + + for ($cspi = 0; $cspi < $ccolsp; $cspi++) { + + // already defined Top for adjacent cell below + if (isset($cells[($i + $crowsp)][$j + $cspi])) { + if ($this->packTableData) { + $adjc = $cells[($i + $crowsp)][$j + $cspi]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[($i + $crowsp)][$j + $cspi]; + } + } else { + $celladj = false; + } + + if (isset($celladj['border_details']['T']['s']) && $celladj['border_details']['T']['s'] == 1) { + + $csadj = $celladj['border_details']['T']['w']; + $csthis = $cbord['border_details']['B']['w']; + + // Hidden + if ($cbord['border_details']['B']['style'] == 'hidden') { + + $celladj['border_details']['T'] = $cbord['border_details']['B']; + $this->setBorder($celladj['border'], Border::TOP, false); + $this->setBorder($cbord['border'], Border::BOTTOM, false); + + } elseif ($celladj['border_details']['T']['style'] == 'hidden') { + + $cbord['border_details']['B'] = $celladj['border_details']['T']; + $this->setBorder($cbord['border'], Border::BOTTOM, false); + $this->setBorder($celladj['border'], Border::TOP, false); + + } elseif ($csthis > $csadj) { // Width + + if (!isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) || (isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) && $cells[($i + $crowsp)][$j + $cspi]['colspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['T'] = $cbord['border_details']['B']; + $this->setBorder($cbord['border'], Border::BOTTOM); + } + + } elseif ($csadj > $csthis) { + + if ($ccolsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['B'] = $celladj['border_details']['T']; + $this->setBorder($celladj['border'], Border::TOP); + } + + } elseif (array_search($cbord['border_details']['B']['style'], $this->borderstyles) > array_search($celladj['border_details']['T']['style'], $this->borderstyles)) { // double>solid>dashed>dotted... + + if (!isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) || (isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) && $cells[($i + $crowsp)][$j + $cspi]['colspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['T'] = $cbord['border_details']['B']; + $this->setBorder($cbord['border'], Border::BOTTOM); + } + + } elseif (array_search($celladj['border_details']['T']['style'], $this->borderstyles) > array_search($cbord['border_details']['B']['style'], $this->borderstyles)) { + + if ($ccolsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['B'] = $celladj['border_details']['T']; + $this->setBorder($celladj['border'], Border::TOP); + } + + } elseif ($celladj['border_details']['T']['dom'] > $celladj['border_details']['B']['dom']) { // Style set on cell vs. table + + if ($ccolsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['B'] = $celladj['border_details']['T']; + $this->setBorder($celladj['border'], Border::TOP); + } + + } else { // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT + + if (!isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) || (isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) && $cells[($i + $crowsp)][$j + $cspi]['colspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['T'] = $cbord['border_details']['B']; + $this->setBorder($cbord['border'], Border::BOTTOM); + } + + } + + } elseif ($celladj) { + + if (!isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) || (isset($cells[($i + $crowsp)][$j + $cspi]['colspan']) && $cells[($i + $crowsp)][$j + $cspi]['colspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['T'] = $cbord['border_details']['B']; + } + + } + + // mPDF 5.7.4 + if ($celladj && $this->packTableData) { + $cells[$i + $crowsp][$j + $cspi]['borderbin'] = $this->_packCellBorder($celladj); + } + + unset($celladj); + } + } + + if ($j < ($numcols - 1) || ($j + $ccolsp) < $numcols) { // Right-Left + + for ($cspi = 0; $cspi < $crowsp; $cspi++) { + + // already defined Left for adjacent cell to R + if (isset($cells[($i + $cspi)][$j + $ccolsp])) { + if ($this->packTableData) { + $adjc = $cells[($i + $cspi)][$j + $ccolsp]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[$i + $cspi][$j + $ccolsp]; + } + } else { + $celladj = false; + } + if ($celladj && $celladj['border_details']['L']['s'] == 1) { + $csadj = $celladj['border_details']['L']['w']; + $csthis = $cbord['border_details']['R']['w']; + // Hidden + if ($cbord['border_details']['R']['style'] == 'hidden') { + $celladj['border_details']['L'] = $cbord['border_details']['R']; + $this->setBorder($celladj['border'], Border::LEFT, false); + $this->setBorder($cbord['border'], Border::RIGHT, false); + } elseif ($celladj['border_details']['L']['style'] == 'hidden') { + $cbord['border_details']['R'] = $celladj['border_details']['L']; + $this->setBorder($cbord['border'], Border::RIGHT, false); + $this->setBorder($celladj['border'], Border::LEFT, false); + } // Width + elseif ($csthis > $csadj) { + if (!isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) || (isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) && $cells[($i + $cspi)][$j + $ccolsp]['rowspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['L'] = $cbord['border_details']['R']; + $this->setBorder($cbord['border'], Border::RIGHT); + $this->setBorder($celladj['border'], Border::LEFT, false); + } + } elseif ($csadj > $csthis) { + if ($crowsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['R'] = $celladj['border_details']['L']; + $this->setBorder($cbord['border'], Border::RIGHT, false); + $this->setBorder($celladj['border'], Border::LEFT); + } + } // double>solid>dashed>dotted... + elseif (array_search($cbord['border_details']['R']['style'], $this->borderstyles) > array_search($celladj['border_details']['L']['style'], $this->borderstyles)) { + if (!isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) || (isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) && $cells[($i + $cspi)][$j + $ccolsp]['rowspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['L'] = $cbord['border_details']['R']; + $this->setBorder($celladj['border'], Border::LEFT, false); + $this->setBorder($cbord['border'], Border::RIGHT); + } + } elseif (array_search($celladj['border_details']['L']['style'], $this->borderstyles) > array_search($cbord['border_details']['R']['style'], $this->borderstyles)) { + if ($crowsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['R'] = $celladj['border_details']['L']; + $this->setBorder($cbord['border'], Border::RIGHT, false); + $this->setBorder($celladj['border'], Border::LEFT); + } + } // Style set on cell vs. table + elseif ($celladj['border_details']['L']['dom'] > $cbord['border_details']['R']['dom']) { + if ($crowsp < 2) { // don't overwrite this cell if it spans + $cbord['border_details']['R'] = $celladj['border_details']['L']; + $this->setBorder($celladj['border'], Border::LEFT); + } + } // Style set on cell vs. table - OR - LEFT/TOP (cell) in preference to BOTTOM/RIGHT + else { + if (!isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) || (isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) && $cells[($i + $cspi)][$j + $ccolsp]['rowspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['L'] = $cbord['border_details']['R']; + $this->setBorder($cbord['border'], Border::RIGHT); + } + } + } elseif ($celladj) { + // if right-cell border is not set + if (!isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) || (isset($cells[($i + $cspi)][$j + $ccolsp]['rowspan']) && $cells[($i + $cspi)][$j + $ccolsp]['rowspan'] < 2)) { // don't overwrite bordering cells that span + $celladj['border_details']['L'] = $cbord['border_details']['R']; + } + } + // mPDF 5.7.4 + if ($celladj && $this->packTableData) { + $cells[$i + $cspi][$j + $ccolsp]['borderbin'] = $this->_packCellBorder($celladj); + } + unset($celladj); + } + } + } + + + // Set maximum cell border width meeting at LRTB edges of cell - used for extended cell border + // ['border_details']['mbw']['LT'] = meeting border width - Left border - Top end + if (!$table['borders_separate']) { + + $cbord['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['BL'], $cbord['border_details']['L']['w']); + $cbord['border_details']['mbw']['BR'] = max($cbord['border_details']['mbw']['BR'], $cbord['border_details']['R']['w']); + $cbord['border_details']['mbw']['RT'] = max($cbord['border_details']['mbw']['RT'], $cbord['border_details']['T']['w']); + $cbord['border_details']['mbw']['RB'] = max($cbord['border_details']['mbw']['RB'], $cbord['border_details']['B']['w']); + $cbord['border_details']['mbw']['TL'] = max($cbord['border_details']['mbw']['TL'], $cbord['border_details']['L']['w']); + $cbord['border_details']['mbw']['TR'] = max($cbord['border_details']['mbw']['TR'], $cbord['border_details']['R']['w']); + $cbord['border_details']['mbw']['LT'] = max($cbord['border_details']['mbw']['LT'], $cbord['border_details']['T']['w']); + $cbord['border_details']['mbw']['LB'] = max($cbord['border_details']['mbw']['LB'], $cbord['border_details']['B']['w']); + + if (($i + $crowsp) < $numrows && isset($cells[$i + $crowsp][$j])) { // Has Bottom adjoining cell + + if ($this->packTableData) { + $adjc = $cells[$i + $crowsp][$j]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[$i + $crowsp][$j]; + } + + $cbord['border_details']['mbw']['BL'] = max( + $cbord['border_details']['mbw']['BL'], + $celladj ? $celladj['border_details']['L']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['TL']: 0 + ); + + $cbord['border_details']['mbw']['BR'] = max( + $cbord['border_details']['mbw']['BR'], + $celladj ? $celladj['border_details']['R']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['TR']: 0 + ); + + $cbord['border_details']['mbw']['LB'] = max( + $cbord['border_details']['mbw']['LB'], + $celladj ? $celladj['border_details']['mbw']['LT'] : 0 + ); + + $cbord['border_details']['mbw']['RB'] = max( + $cbord['border_details']['mbw']['RB'], + $celladj ? $celladj['border_details']['mbw']['RT'] : 0 + ); + + unset($celladj); + } + + if (($j + $ccolsp) < $numcols && isset($cells[$i][$j + $ccolsp])) { // Has Right adjoining cell + + if ($this->packTableData) { + $adjc = $cells[$i][$j + $ccolsp]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[$i][$j + $ccolsp]; + } + + $cbord['border_details']['mbw']['RT'] = max( + $cbord['border_details']['mbw']['RT'], + $celladj ? $celladj['border_details']['T']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['LT'] : 0 + ); + + $cbord['border_details']['mbw']['RB'] = max( + $cbord['border_details']['mbw']['RB'], + $celladj ? $celladj['border_details']['B']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['LB'] : 0 + ); + + $cbord['border_details']['mbw']['TR'] = max( + $cbord['border_details']['mbw']['TR'], + $celladj ? $celladj['border_details']['mbw']['TL'] : 0 + ); + + $cbord['border_details']['mbw']['BR'] = max( + $cbord['border_details']['mbw']['BR'], + $celladj ? $celladj['border_details']['mbw']['BL'] : 0 + ); + + unset($celladj); + } + + if ($i > 0 && isset($cells[$i - 1][$j]) && is_array($cells[$i - 1][$j]) && (($this->packTableData && $cells[$i - 1][$j]['borderbin']) || $cells[$i - 1][$j]['border'])) { // Has Top adjoining cell + + if ($this->packTableData) { + $adjc = $cells[$i - 1][$j]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[$i - 1][$j]; + } + + $cbord['border_details']['mbw']['TL'] = max( + $cbord['border_details']['mbw']['TL'], + $celladj ? $celladj['border_details']['L']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['BL'] : 0 + ); + + $cbord['border_details']['mbw']['TR'] = max( + $cbord['border_details']['mbw']['TR'], + $celladj ? $celladj['border_details']['R']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['BR'] : 0 + ); + + $cbord['border_details']['mbw']['LT'] = max( + $cbord['border_details']['mbw']['LT'], + $celladj ? $celladj['border_details']['mbw']['LB'] : 0 + ); + + $cbord['border_details']['mbw']['RT'] = max( + $cbord['border_details']['mbw']['RT'], + $celladj ? $celladj['border_details']['mbw']['RB'] : 0 + ); + + if ($celladj['border_details']['mbw']['BL']) { + $celladj['border_details']['mbw']['BL'] = max($cbord['border_details']['mbw']['TL'], $celladj['border_details']['mbw']['BL']); + } + + if ($celladj['border_details']['mbw']['BR']) { + $celladj['border_details']['mbw']['BR'] = max($celladj['border_details']['mbw']['BR'], $cbord['border_details']['mbw']['TR']); + } + + if ($this->packTableData) { + $cells[$i - 1][$j]['borderbin'] = $this->_packCellBorder($celladj); + } + unset($celladj); + } + + if ($j > 0 && isset($cells[$i][$j - 1]) && is_array($cells[$i][$j - 1]) && (($this->packTableData && $cells[$i][$j - 1]['borderbin']) || $cells[$i][$j - 1]['border'])) { // Has Left adjoining cell + + if ($this->packTableData) { + $adjc = $cells[$i][$j - 1]; + $celladj = $this->_unpackCellBorder($adjc['borderbin']); + } else { + $celladj = & $cells[$i][$j - 1]; + } + + $cbord['border_details']['mbw']['LT'] = max( + $cbord['border_details']['mbw']['LT'], + $celladj ? $celladj['border_details']['T']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['RT'] : 0 + ); + + $cbord['border_details']['mbw']['LB'] = max( + $cbord['border_details']['mbw']['LB'], + $celladj ? $celladj['border_details']['B']['w'] : 0, + $celladj ? $celladj['border_details']['mbw']['RB'] : 0 + ); + + $cbord['border_details']['mbw']['BL'] = max( + $cbord['border_details']['mbw']['BL'], + $celladj ? $celladj['border_details']['mbw']['BR'] : 0 + ); + + $cbord['border_details']['mbw']['TL'] = max( + $cbord['border_details']['mbw']['TL'], + $celladj ? $celladj['border_details']['mbw']['TR'] : 0 + ); + + if ($celladj['border_details']['mbw']['RT']) { + $celladj['border_details']['mbw']['RT'] = max($celladj['border_details']['mbw']['RT'], $cbord['border_details']['mbw']['LT']); + } + + if ($celladj['border_details']['mbw']['RB']) { + $celladj['border_details']['mbw']['RB'] = max($celladj['border_details']['mbw']['RB'], $cbord['border_details']['mbw']['LB']); + } + + if ($this->packTableData) { + $cells[$i][$j - 1]['borderbin'] = $this->_packCellBorder($celladj); + } + + unset($celladj); + } + + + // Update maximum cell border width at LRTB edges of table - used for overall table width + if ($j == 0 && $cbord['border_details']['L']['w']) { + $table['max_cell_border_width']['L'] = max($table['max_cell_border_width']['L'], $cbord['border_details']['L']['w']); + } + if (($j == ($numcols - 1) || ($j + $ccolsp) == $numcols ) && $cbord['border_details']['R']['w']) { + $table['max_cell_border_width']['R'] = max($table['max_cell_border_width']['R'], $cbord['border_details']['R']['w']); + } + if ($i == 0 && $cbord['border_details']['T']['w']) { + $table['max_cell_border_width']['T'] = max($table['max_cell_border_width']['T'], $cbord['border_details']['T']['w']); + } + if (($i == ($numrows - 1) || ($i + $crowsp) == $numrows ) && $cbord['border_details']['B']['w']) { + $table['max_cell_border_width']['B'] = max($table['max_cell_border_width']['B'], $cbord['border_details']['B']['w']); + } + } + /* -- END TABLES-ADVANCED-BORDERS -- */ + + if ($this->packTableData) { + $cell['borderbin'] = $this->_packCellBorder($cbord); + } + + unset($cbord); + + unset($cell); + } + } + } + unset($cell); + } + + // END FIX BORDERS ************************************************************************************ + + function _reverseTableDir(&$table) + { + $cells = &$table['cells']; + $numcols = $table['nc']; + $numrows = $table['nr']; + for ($i = 0; $i < $numrows; $i++) { // Rows + $row = []; + for ($j = ($numcols - 1); $j >= 0; $j--) { // Columns + if (isset($cells[$i][$j]) && $cells[$i][$j]) { + $cell = &$cells[$i][$j]; + $col = $numcols - $j - 1; + if (isset($cell['colspan']) && $cell['colspan'] > 1) { + $col -= ($cell['colspan'] - 1); + } + // Nested content + if (isset($cell['textbuffer'])) { + for ($n = 0; $n < count($cell['textbuffer']); $n++) { + $t = $cell['textbuffer'][$n][0]; + if (substr($t, 0, 19) == Mpdf::OBJECT_IDENTIFIER . "type=nestedtable") { + $objattr = $this->_getObjAttr($t); + $objattr['col'] = $col; + $cell['textbuffer'][$n][0] = Mpdf::OBJECT_IDENTIFIER . "type=nestedtable,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + $this->table[($this->tableLevel + 1)][$objattr['nestedcontent']]['nestedpos'][1] = $col; + } + } + } + $row[$col] = $cells[$i][$j]; + unset($cell); + } + } + for ($f = 0; $f < $numcols; $f++) { + if (!isset($row[$f])) { + $row[$f] = 0; + } + } + $table['cells'][$i] = $row; + } + } + + function _tableWrite(&$table, $split = false, $startrow = 0, $startcol = 0, $splitpg = 0, $rety = 0) + { + $level = $table['level']; + $levelid = $table['levelid']; + + $cells = &$table['cells']; + $numcols = $table['nc']; + $numrows = $table['nr']; + $maxbwtop = 0; + if ($this->ColActive && $level == 1) { + $this->breakpoints[$this->CurrCol][] = $this->y; + } // *COLUMNS* + + if (!$split || ($startrow == 0 && $splitpg == 0) || $startrow > 0) { + // TABLE TOP MARGIN + if ($table['margin']['T']) { + if (!$this->table_rotate && $level == 1) { + $this->DivLn($table['margin']['T'], $this->blklvl, true, 1); // collapsible + } else { + $this->y += ($table['margin']['T']); + } + } + // Advance down page by half width of top border + if ($table['borders_separate']) { + if ($startrow > 0 && (!isset($table['is_thead']) || count($table['is_thead']) == 0)) { + $adv = $table['border_spacing_V'] / 2; + } else { + $adv = $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2; + } + } else { + $adv = $table['max_cell_border_width']['T'] / 2; + } + if (!$this->table_rotate && $level == 1) { + $this->DivLn($adv); + } else { + $this->y += $adv; + } + } + + if ($level == 1) { + $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w']; + $x0 = $this->x; + $y0 = $this->y; + $right = $x0 + $this->blk[$this->blklvl]['inner_width']; + $outerfilled = $this->y; // Keep track of how far down the outer DIV bgcolor is painted (NB rowspans) + $this->outerfilled = $this->y; + $this->colsums = []; + } else { + $x0 = $this->x; + $y0 = $this->y; + $right = $x0 + $table['w']; + } + + if ($this->table_rotate) { + $temppgwidth = $this->tbrot_maxw; + $this->PageBreakTrigger = $pagetrigger = $y0 + ($this->blk[$this->blklvl]['inner_width']); + if ($level == 1) { + $this->tbrot_y0 = $this->y - $adv - $table['margin']['T']; + $this->tbrot_x0 = $this->x; + $this->tbrot_w = $table['w']; + if ($table['borders_separate']) { + $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2; + } else { + $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['max_cell_border_width']['T']; + } + } + } else { + $this->PageBreakTrigger = $pagetrigger = ($this->h - $this->bMargin); + if ($level == 1) { + $temppgwidth = $this->blk[$this->blklvl]['inner_width']; + if (isset($table['a']) and ( $table['w'] < $this->blk[$this->blklvl]['inner_width'])) { + if ($table['a'] == 'C') { + $x0 += ((($right - $x0) - $table['w']) / 2); + } elseif ($table['a'] == 'R') { + $x0 = $right - $table['w']; + } + } + } else { + $temppgwidth = $table['w']; + } + } + if (!isset($table['overflow'])) { + $table['overflow'] = null; + } + if ($table['overflow'] == 'hidden' && $level == 1 && !$this->table_rotate && !$this->ColActive) { + // Bounding rectangle to clip + $this->tableClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n', $x0 * Mpdf::SCALE, $this->h * Mpdf::SCALE, $this->blk[$this->blklvl]['inner_width'] * Mpdf::SCALE, -$this->h * Mpdf::SCALE); + $this->writer->write($this->tableClipPath); + } else { + $this->tableClipPath = ''; + } + + + if ($table['borders_separate']) { + $indent = $table['margin']['L'] + $table['border_details']['L']['w'] + $table['padding']['L'] + $table['border_spacing_H'] / 2; + } else { + $indent = $table['margin']['L'] + $table['max_cell_border_width']['L'] / 2; + } + $x0 += $indent; + + $returny = 0; + $lastCol = 0; + $tableheader = []; + $tablefooter = []; + $tableheaderrowheight = 0; + $tablefooterrowheight = 0; + $footery = 0; + + // mPD 3.0 Set the Page & Column where table starts + if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN + $tablestartpage = 'EVEN'; + } elseif (($this->mirrorMargins) && (($this->page) % 2 == 1)) { // ODD + $tablestartpage = 'ODD'; + } else { + $tablestartpage = ''; + } + if ($this->ColActive) { + $tablestartcolumn = $this->CurrCol; + } else { + $tablestartcolumn = ''; + } + + $y = $h = 0; + for ($i = 0; $i < $numrows; $i++) { // Rows + if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i] && $level == 1) { + $tablefooterrowheight += $table['hr'][$i]; + $tablefooter[$i][0]['trbackground-images'] = $table['trbackground-images'][$i]; + $tablefooter[$i][0]['trgradients'] = $table['trgradients'][$i]; + $tablefooter[$i][0]['trbgcolor'] = $table['bgcolor'][$i]; + for ($j = $startcol; $j < $numcols; $j++) { // Columns + if (isset($cells[$i][$j]) && $cells[$i][$j]) { + $cell = &$cells[$i][$j]; + if ($split) { + if ($table['colPg'][$j] != $splitpg) { + continue; + } + list($x, $w) = $this->_splitTableGetWidth($table, $i, $j); + $js = $j - $startcol; + } else { + list($x, $w) = $this->_tableGetWidth($table, $i, $j); + $js = $j; + } + + list($y, $h) = $this->_tableGetHeight($table, $i, $j); + $x += $x0; + $y += $y0; + // Get info of tfoot ==>> table footer + $tablefooter[$i][$js]['x'] = $x; + $tablefooter[$i][$js]['y'] = $y; + $tablefooter[$i][$js]['h'] = $h; + $tablefooter[$i][$js]['w'] = $w; + if (isset($cell['textbuffer'])) { + $tablefooter[$i][$js]['textbuffer'] = $cell['textbuffer']; + } else { + $tablefooter[$i][$js]['textbuffer'] = ''; + } + $tablefooter[$i][$js]['a'] = $cell['a']; + $tablefooter[$i][$js]['R'] = $cell['R']; + $tablefooter[$i][$js]['va'] = $cell['va']; + $tablefooter[$i][$js]['mih'] = $cell['mih']; + if (isset($cell['gradient'])) { + $tablefooter[$i][$js]['gradient'] = $cell['gradient']; // *BACKGROUNDS* + } + if (isset($cell['background-image'])) { + $tablefooter[$i][$js]['background-image'] = $cell['background-image']; // *BACKGROUNDS* + } + + // CELL FILL BGCOLOR + if (!$this->simpleTables) { + if ($this->packTableData) { + $c = $this->_unpackCellBorder($cell['borderbin']); + $tablefooter[$i][$js]['border'] = $c['border']; + $tablefooter[$i][$js]['border_details'] = $c['border_details']; + } else { + $tablefooter[$i][$js]['border'] = $cell['border']; + $tablefooter[$i][$js]['border_details'] = $cell['border_details']; + } + } elseif ($this->simpleTables) { + $tablefooter[$i][$js]['border'] = $table['simple']['border']; + $tablefooter[$i][$js]['border_details'] = $table['simple']['border_details']; + } + $tablefooter[$i][$js]['bgcolor'] = $cell['bgcolor']; + $tablefooter[$i][$js]['padding'] = $cell['padding']; + if (isset($cell['rowspan'])) { + $tablefooter[$i][$js]['rowspan'] = $cell['rowspan']; + } + if (isset($cell['colspan'])) { + $tablefooter[$i][$js]['colspan'] = $cell['colspan']; + } + if (isset($cell['direction'])) { + $tablefooter[$i][$js]['direction'] = $cell['direction']; + } + if (isset($cell['cellLineHeight'])) { + $tablefooter[$i][$js]['cellLineHeight'] = $cell['cellLineHeight']; + } + if (isset($cell['cellLineStackingStrategy'])) { + $tablefooter[$i][$js]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy']; + } + if (isset($cell['cellLineStackingShift'])) { + $tablefooter[$i][$js]['cellLineStackingShift'] = $cell['cellLineStackingShift']; + } + } + } + } + } + + if ($level == 1) { + $this->writer->write('___TABLE___BACKGROUNDS' . $this->uniqstr); + } + $tableheaderadj = 0; + $tablefooteradj = 0; + + $tablestartpageno = $this->page; + + // Draw Table Contents and Borders + for ($i = 0; $i < $numrows; $i++) { // Rows + if ($split && $startrow > 0) { + $thnr = (isset($table['is_thead']) ? count($table['is_thead']) : 0); + if ($i >= $thnr && $i < $startrow) { + continue; + } + if ($i == $startrow) { + $returny = $rety - $tableheaderrowheight; + } + } + + // Get Maximum row/cell height in row - including rowspan>1 + 1 overlapping + $maxrowheight = $this->_tableGetMaxRowHeight($table, $i); + + $skippage = false; + $newpagestarted = false; + for ($j = $startcol; $j < $numcols; $j++) { // Columns + if ($split) { + if ($table['colPg'][$j] > $splitpg) { + break; + } + $lastCol = $j; + } + if (isset($cells[$i][$j]) && $cells[$i][$j]) { + $cell = &$cells[$i][$j]; + if ($split) { + $lastCol = $j + (isset($cell['colspan']) ? ($cell['colspan'] - 1) : 0); + list($x, $w) = $this->_splitTableGetWidth($table, $i, $j); + } else { + list($x, $w) = $this->_tableGetWidth($table, $i, $j); + } + + list($y, $h) = $this->_tableGetHeight($table, $i, $j); + $x += $x0; + $y += $y0; + $y -= $returny; + + if ($table['borders_separate']) { + if (!empty($tablefooter) || $i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i + 1) == $numrows)) { + $extra = $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + // $extra = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V']/2; + } else { + $extra = $table['border_spacing_V'] / 2; + } + } else { + $extra = $table['max_cell_border_width']['B'] / 2; + } + + // lookahead for pagebreak + $pagebreaklookahead = 1; + while (isset($table['pagebreak-before']) && isset($table['pagebreak-before'][$i + $pagebreaklookahead]) && $table['pagebreak-before'][$i + $pagebreaklookahead] == 'avoid') { + // pagebreak-after is mapped to pagebreak-before on i+1 in Tags/Tr.php + $pagebreaklookahead++; + } + if ($j == $startcol && ((($y + $pagebreaklookahead * $maxrowheight + $extra ) > ($pagetrigger + 0.001)) || (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && ($y + $maxrowheight + $tablefooterrowheight + $extra) > $pagetrigger) && ($this->tableLevel == 1 && $i < ($numrows - $table['headernrows']))) && ($y0 > 0 || $x0 > 0) && !$this->InFooter && $this->autoPageBreak) { + if (!$skippage) { + $finalSpread = true; + $firstSpread = true; + if ($split) { + for ($t = $startcol; $t < $numcols; $t++) { + // Are there more columns to print on a next page? + if ($table['colPg'][$t] > $splitpg) { + $finalSpread = false; + break; + } + } + if ($startcol > 0) { + $firstSpread = false; + } + } + + if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0) { + $this->y = $y; + $ya = $this->y; + $this->TableHeaderFooter($tablefooter, $tablestartpage, $tablestartcolumn, 'F', $level, $firstSpread, $finalSpread); + if ($this->table_rotate) { + $this->tbrot_h += $this->y - $ya; + } + $tablefooteradj = $this->y - $ya; + } + $y -= $y0; + $returny += $y; + + $oldcolumn = $this->CurrCol; + if ($this->AcceptPageBreak()) { + $newpagestarted = true; + $this->y = $y + $y0; + + // Move down to account for border-spacing or + // extra half border width in case page breaks in middle + if ($i > 0 && !$this->table_rotate && $level == 1 && !$this->ColActive) { + if ($table['borders_separate']) { + $adv = $table['border_spacing_V'] / 2; + // If table footer + if (($this->keepColumns || !$this->ColActive) && !empty($tablefooter) && $i > 0) { + $adv += ($table['padding']['B'] + $table['border_details']['B']['w']); + } + } else { + $maxbwtop = 0; + $maxbwbottom = 0; + if (!$this->simpleTables) { + if (!empty($tablefooter)) { + $maxbwbottom = $table['max_cell_border_width']['B']; + } else { + $brow = $i - 1; + for ($ctj = 0; $ctj < $numcols; $ctj++) { + if (isset($cells[$brow][$ctj]) && $cells[$brow][$ctj]) { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($cells[$brow][$ctj]['borderbin']); + } else { + $bb = $cells[$brow][$ctj]['border_details']['B']['w']; + } + $maxbwbottom = max($maxbwbottom, $bb); + } + } + } + if (!empty($tableheader)) { + $maxbwtop = $table['max_cell_border_width']['T']; + } else { + $trow = $i - 1; + for ($ctj = 0; $ctj < $numcols; $ctj++) { + if (isset($cells[$trow][$ctj]) && $cells[$trow][$ctj]) { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($cells[$trow][$ctj]['borderbin']); + } else { + $bt = $cells[$trow][$ctj]['border_details']['T']['w']; + } + $maxbwtop = max($maxbwtop, $bt); + } + } + } + } elseif ($this->simpleTables) { + $maxbwtop = $table['simple']['border_details']['T']['w']; + $maxbwbottom = $table['simple']['border_details']['B']['w']; + } + $adv = $maxbwbottom / 2; + } + $this->y += $adv; + } + + // Rotated table split over pages - needs this->y for borders/backgrounds + if ($i > 0 && $this->table_rotate && $level == 1) { + // $this->y = $y0 + $this->tbrot_w; + } + + if ($this->tableClipPath) { + $this->writer->write("Q"); + } + + $bx = $x0; + $by = $y0; + + if ($table['borders_separate']) { + $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'] / 2); + if ($tablestartpageno != $this->page) { // IF already broken across a previous pagebreak + $by += $table['max_cell_border_width']['T'] / 2; + if (empty($tableheader)) { + $by -= ($table['border_spacing_V'] / 2); + } + } else { + $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2); + } + } elseif ($tablestartpageno != $this->page && !empty($tableheader)) { + $by += $maxbwtop / 2; + } + + $by -= $tableheaderadj; + $bh = $this->y - $by + $tablefooteradj; + if (!$table['borders_separate']) { + $bh -= $adv; + } + if ($split) { + $bw = 0; + for ($t = $startcol; $t < $numcols; $t++) { + if ($table['colPg'][$t] == $splitpg) { + $bw += $table['wc'][$t]; + } + if ($table['colPg'][$t] > $splitpg) { + break; + } + } + if ($table['borders_separate']) { + if ($firstSpread) { + $bw += $table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H']; + } else { + $bx += ($table['padding']['L'] + $table['border_details']['L']['w']); + $bw += $table['border_spacing_H']; + } + if ($finalSpread) { + $bw += $table['padding']['R'] + $table['border_details']['R']['w'] / 2 + $table['border_spacing_H']; + } + } + } else { + $bw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + } + + if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tablefooter) && $i > 0 && $table['border_details']['B']['w']) { + $prevDrawColor = $this->DrawColor; + $lw = $this->LineWidth; + $this->SetLineWidth($this->splitTableBorderWidth); + $this->SetDColor($table['border_details']['B']['c']); + $this->SetLineJoin(0); + $this->SetLineCap(0); + $blx = $bx; + $blw = $bw; + if (!$table['borders_separate']) { + $blx -= ($table['max_cell_border_width']['L'] / 2); + $blw += ($table['max_cell_border_width']['L'] / 2 + $table['max_cell_border_width']['R'] / 2); + } + $this->Line($blx, $this->y + ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y + ($this->splitTableBorderWidth / 2)); + $this->DrawColor = $prevDrawColor; + $this->writer->write($this->DrawColor); + $this->SetLineWidth($lw); + $this->SetLineJoin(2); + $this->SetLineCap(2); + } + + if (!$this->ColActive && ($i > 0 || $j > 0)) { + if (isset($table['bgcolor'][-1])) { + $color = $this->colorConverter->convert($table['bgcolor'][-1], $this->PDFAXwarnings); + if ($color) { + if (!$table['borders_separate']) { + $bh -= $table['max_cell_border_width']['B'] / 2; + } + $this->tableBackgrounds[$level * 9][] = ['gradient' => false, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'col' => $color]; + } + } + + /* -- BACKGROUNDS -- */ + if (isset($table['gradient'])) { + $g = $this->gradient->parseBackgroundGradient($table['gradient']); + if ($g) { + $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + + if (isset($table['background-image'])) { + if ($table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'])) { + $g = $this->gradient->parseMozGradient($table['background-image']['gradient']); + if ($g) { + $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } else { + $image_id = $table['background-image']['image_id']; + $orig_w = $table['background-image']['orig_w']; + $orig_h = $table['background-image']['orig_h']; + $x_pos = $table['background-image']['x_pos']; + $y_pos = $table['background-image']['y_pos']; + $x_repeat = $table['background-image']['x_repeat']; + $y_repeat = $table['background-image']['y_repeat']; + $resize = $table['background-image']['resize']; + $opacity = $table['background-image']['opacity']; + $itype = $table['background-image']['itype']; + $this->tableBackgrounds[$level * 9 + 2][] = ['x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } + } + /* -- END BACKGROUNDS -- */ + } + + // $this->AcceptPageBreak() has moved tablebuffer to $this->pages content + if ($this->tableBackgrounds) { + $s = $this->PrintTableBackgrounds(); + if ($this->bufferoutput) { + $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->headerbuffer); + $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->headerbuffer); + } else { + $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]); + $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->pages[$this->page]); + } + $this->tableBackgrounds = []; + } + + if ($split) { + if ($i == 0 && $j == 0) { + $y0 = -1; + } elseif ($finalSpread) { + $splitpg = 0; + $startcol = 0; + $startrow = $i; + } else { + $splitpg++; + $startcol = $t; + $returny -= $y; + } + return [false, $startrow, $startcol, $splitpg, $returny, $y0]; + } + + $this->AddPage($this->CurOrientation); + + $this->writer->write('___TABLE___BACKGROUNDS' . $this->uniqstr); + + + if ($this->tableClipPath) { + $this->writer->write($this->tableClipPath); + } + + // Added to correct for OddEven Margins + $x = $x + $this->MarginCorrection; + $x0 = $x0 + $this->MarginCorrection; + + if ($this->splitTableBorderWidth && ($this->keepColumns || !$this->ColActive) && empty($tableheader) && $i > 0 && $table['border_details']['T']['w']) { + $prevDrawColor = $this->DrawColor; + $lw = $this->LineWidth; + $this->SetLineWidth($this->splitTableBorderWidth); + $this->SetDColor($table['border_details']['T']['c']); + $this->SetLineJoin(0); + $this->SetLineCap(0); + $blx += $this->MarginCorrection; + $this->Line($blx, $this->y - ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y - ($this->splitTableBorderWidth / 2)); + $this->DrawColor = $prevDrawColor; + $this->writer->write($this->DrawColor); + $this->SetLineWidth($lw); + $this->SetLineJoin(2); + $this->SetLineCap(2); + } + + // Move down to account for half of top border-spacing or + // extra half border width in case page was broken in middle + if ($i > 0 && !$this->table_rotate && $level == 1 && $table['headernrows'] == 0) { + if ($table['borders_separate']) { + $adv = $table['border_spacing_V'] / 2; + } else { + $maxbwtop = 0; + for ($ctj = 0; $ctj < $numcols; $ctj++) { + if (isset($cells[$i][$ctj]) && $cells[$i][$ctj]) { + if (!$this->simpleTables) { + if ($this->packTableData) { + list($bt, $br, $bb, $bl) = $this->_getBorderWidths($cells[$i][$ctj]['borderbin']); + } else { + $bt = $cells[$i][$ctj]['border_details']['T']['w']; + } + $maxbwtop = max($maxbwtop, $bt); + } elseif ($this->simpleTables) { + $maxbwtop = max($maxbwtop, $table['simple']['border_details']['T']['w']); + } + } + } + $adv = $maxbwtop / 2; + } + $this->y += $adv; + } + + + if ($this->table_rotate) { + $this->tbrot_x0 = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['padding_left'] + $this->blk[$this->blklvl]['border_left']['w']; + if ($table['borders_separate']) { + $this->tbrot_h = $table['margin']['T'] + $table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2; + } else { + $this->tbrot_h = $table['margin']['T'] + $table['max_cell_border_width']['T']; + } + $this->tbrot_y0 = $this->y; + $pagetrigger = $y0 - $tableheaderadj + ($this->blk[$this->blklvl]['inner_width']); + } else { + $pagetrigger = $this->PageBreakTrigger; + } + + if ($this->kwt_saved && $level == 1) { + $this->kwt_moved = true; + } + + + if (!empty($tableheader)) { + $ya = $this->y; + $this->TableHeaderFooter($tableheader, $tablestartpage, $tablestartcolumn, 'H', $level); + if ($this->table_rotate) { + $this->tbrot_h = $this->y - $ya; + } + $tableheaderadj = $this->y - $ya; + } elseif ($i == 0 && !$this->table_rotate && $level == 1 && !$this->ColActive) { + // Advance down page + if ($table['borders_separate']) { + $adv = $table['border_spacing_V'] / 2 + $table['border_details']['T']['w'] + $table['padding']['T']; + } else { + $adv = $table['max_cell_border_width']['T'] / 2; + } + if ($adv) { + if ($this->table_rotate) { + $this->y += ($adv); + } else { + $this->DivLn($adv, $this->blklvl, true); + } + } + } + + $outerfilled = 0; + $y = $y0 = $this->y; + } + + /* -- COLUMNS -- */ + // COLS + // COLUMN CHANGE + if ($this->CurrCol != $oldcolumn) { + // Added to correct for Columns + $x += $this->ChangeColumn * ($this->ColWidth + $this->ColGap); + $x0 += $this->ChangeColumn * ($this->ColWidth + $this->ColGap); + if ($this->CurrCol == 0) { // just added a page - possibly with tableheader + $y0 = $this->y; // this->y0 is global used by Columns - $y0 is internal to tablewrite + } else { + $y0 = $this->y0; // this->y0 is global used by Columns - $y0 is internal to tablewrite + } + $y = $y0; + $outerfilled = 0; + if ($this->CurrCol != 0 && ($this->keepColumns && $this->ColActive) && !empty($tableheader) && $i > 0) { + $this->x = $x; + $this->y = $y; + $this->TableHeaderFooter($tableheader, $tablestartpage, $tablestartcolumn, 'H', $level); + $y0 = $y = $this->y; + } + } + /* -- END COLUMNS -- */ + } + $skippage = true; + } + + $this->x = $x; + $this->y = $y; + + if ($this->kwt_saved && $level == 1) { + $this->printkwtbuffer(); + $x0 = $x = $this->x; + $y0 = $y = $this->y; + $this->kwt_moved = false; + $this->kwt_saved = false; + } + + + // Set the Page & Column where table actually starts + if ($i == 0 && $j == 0 && $level == 1) { + if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN + $tablestartpage = 'EVEN'; + } elseif (($this->mirrorMargins) && (($this->page) % 2 == 1)) { // ODD + $tablestartpage = 'ODD'; + } else { + $tablestartpage = ''; + } + $tablestartpageno = $this->page; + if ($this->ColActive) { + $tablestartcolumn = $this->CurrCol; + } // *COLUMNS* + } + + // ALIGN + $align = $cell['a']; + + /* -- COLUMNS -- */ + // If outside columns, this is done in PaintDivBB + if ($this->ColActive) { + // OUTER FILL BGCOLOR of DIVS + if ($this->blklvl > 0 && ($j == 0) && !$this->table_rotate && $level == 1) { + $firstblockfill = $this->GetFirstBlockFill(); + if ($firstblockfill && $this->blklvl >= $firstblockfill) { + $divh = $maxrowheight; + // Last row + if ((!isset($cell['rowspan']) && $i == $numrows - 1) || (isset($cell['rowspan']) && (($i == $numrows - 1 && $cell['rowspan'] < 2) || ($cell['rowspan'] > 1 && ($i + $cell['rowspan'] - 1) == $numrows - 1)))) { + if ($table['borders_separate']) { + $adv = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + } else { + $adv = $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2; + } + $divh += $adv; // last row: fill bottom half of bottom border (y advanced at end) + } + + if (($this->y + $divh) > $outerfilled) { // if not already painted by previous rowspan + $bak_x = $this->x; + $bak_y = $this->y; + if ($outerfilled > $this->y) { + $divh = ($this->y + $divh) - $outerfilled; + $this->y = $outerfilled; + } + + $this->DivLn($divh, -3, false); + $outerfilled = $this->y + $divh; + // Reset current block fill + $bcor = $this->blk[$this->blklvl]['bgcolorarray']; + if ($bcor) { + $this->SetFColor($bcor); + } + $this->x = $bak_x; + $this->y = $bak_y; + } + } + } + } + + // TABLE BACKGROUND FILL BGCOLOR - for cellSpacing + if ($this->ColActive) { + if ($table['borders_separate']) { + $fill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0; + if ($fill) { + $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings); + if ($color) { + $xadj = ($table['border_spacing_H'] / 2); + $yadj = ($table['border_spacing_V'] / 2); + $wadj = $table['border_spacing_H']; + $hadj = $table['border_spacing_V']; + if ($i == 0) { // Top + $yadj += $table['padding']['T'] + $table['border_details']['T']['w']; + $hadj += $table['padding']['T'] + $table['border_details']['T']['w']; + } + if ($j == 0) { // Left + $xadj += $table['padding']['L'] + $table['border_details']['L']['w']; + $wadj += $table['padding']['L'] + $table['border_details']['L']['w']; + } + if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i + 1) == $numrows)) { // Bottom + $hadj += $table['padding']['B'] + $table['border_details']['B']['w']; + } + if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols) || (!isset($cell['colspan']) && ($j + 1) == $numcols)) { // Right + $wadj += $table['padding']['R'] + $table['border_details']['R']['w']; + } + $this->SetFColor($color); + $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F'); + } + } + } + } + /* -- END COLUMNS -- */ + + if ($table['empty_cells'] != 'hide' || !empty($cell['textbuffer']) || (isset($cell['nestedcontent']) && $cell['nestedcontent']) || !$table['borders_separate']) { + $paintcell = true; + } else { + $paintcell = false; + } + + // Set Borders + $bord = 0; + $bord_det = []; + + if (!$this->simpleTables) { + if ($this->packTableData) { + $c = $this->_unpackCellBorder($cell['borderbin']); + $bord = $c['border']; + $bord_det = $c['border_details']; + } else { + $bord = $cell['border']; + $bord_det = $cell['border_details']; + } + } elseif ($this->simpleTables) { + $bord = $table['simple']['border']; + $bord_det = $table['simple']['border_details']; + } + + // TABLE ROW OR CELL FILL BGCOLOR + $fill = 0; + if (isset($cell['bgcolor']) && $cell['bgcolor'] && $cell['bgcolor'] != 'transparent') { + $fill = $cell['bgcolor']; + $leveladj = 6; + } elseif (isset($table['bgcolor'][$i]) && $table['bgcolor'][$i] && $table['bgcolor'][$i] != 'transparent') { // Row color + $fill = $table['bgcolor'][$i]; + $leveladj = 3; + } + if ($fill && $paintcell) { + $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings); + if ($color) { + if ($table['borders_separate']) { + if ($this->ColActive) { + $this->SetFColor($color); + $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F'); + } else { + $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color]; + } + } else { + if ($this->ColActive) { + $this->SetFColor($color); + $this->Rect($x, $y, $w, $h, 'F'); + } else { + $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color]; + } + } + } + } + + /* -- BACKGROUNDS -- */ + if (isset($cell['gradient']) && $cell['gradient'] && $paintcell) { + $g = $this->gradient->parseBackgroundGradient($cell['gradient']); + if ($g) { + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']); + } else { + $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } + + if (isset($cell['background-image']) && $paintcell) { + if (isset($cell['background-image']['gradient']) && $cell['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $cell['background-image']['gradient'])) { + $g = $this->gradient->parseMozGradient($cell['background-image']['gradient']); + if ($g) { + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']); + } else { + $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } elseif (isset($cell['background-image']['image_id']) && $cell['background-image']['image_id']) { // Background pattern + $n = count($this->patterns) + 1; + if ($table['borders_separate']) { + $px = $x + ($table['border_spacing_H'] / 2); + $py = $y + ($table['border_spacing_V'] / 2); + $pw = $w - $table['border_spacing_H']; + $ph = $h - $table['border_spacing_V']; + } else { + $px = $x; + $py = $y; + $pw = $w; + $ph = $h; + } + if ($this->ColActive) { + list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($cell['background-image']['orig_w'], $cell['background-image']['orig_h'], $pw, $ph, $cell['background-image']['resize'], $cell['background-image']['x_repeat'], $cell['background-image']['y_repeat']); + $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $cell['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $cell['background-image']['x_pos'], 'y_pos' => $cell['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat]; + if ($cell['background-image']['opacity'] > 0 && $cell['background-image']['opacity'] < 1) { + $opac = $this->SetAlpha($cell['background-image']['opacity'], 'Normal', true); + } else { + $opac = ''; + } + $this->writer->write(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE)); + } else { + $image_id = $cell['background-image']['image_id']; + $orig_w = $cell['background-image']['orig_w']; + $orig_h = $cell['background-image']['orig_h']; + $x_pos = $cell['background-image']['x_pos']; + $y_pos = $cell['background-image']['y_pos']; + $x_repeat = $cell['background-image']['x_repeat']; + $y_repeat = $cell['background-image']['y_repeat']; + $resize = $cell['background-image']['resize']; + $opacity = $cell['background-image']['opacity']; + $itype = $cell['background-image']['itype']; + $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } + } + } + /* -- END BACKGROUNDS -- */ + + if (isset($cell['colspan']) && $cell['colspan'] > 1) { + $ccolsp = $cell['colspan']; + } else { + $ccolsp = 1; + } + if (isset($cell['rowspan']) && $cell['rowspan'] > 1) { + $crowsp = $cell['rowspan']; + } else { + $crowsp = 1; + } + + + // but still need to do this for repeated headers... + if (!$table['borders_separate'] && $this->tabletheadjustfinished && !$this->simpleTables) { + if (isset($table['topntail']) && $table['topntail']) { + $bord_det['T'] = $this->border_details($table['topntail']); + $bord_det['T']['w'] /= $this->shrin_k; + $this->setBorder($bord, Border::TOP); + } + if (isset($table['thead-underline']) && $table['thead-underline']) { + $bord_det['T'] = $this->border_details($table['thead-underline']); + $bord_det['T']['w'] /= $this->shrin_k; + $this->setBorder($bord, Border::TOP); + } + } + + + // Get info of first row ==>> table header + // Use > 1 row if THEAD + if (isset($table['is_thead'][$i]) && $table['is_thead'][$i] && $level == 1) { + if ($j == 0) { + $tableheaderrowheight += $table['hr'][$i]; + } + $tableheader[$i][0]['trbackground-images'] = (isset($table['trbackground-images'][$i]) ? $table['trbackground-images'][$i] : null); + $tableheader[$i][0]['trgradients'] = (isset($table['trgradients'][$i]) ? $table['trgradients'][$i] : null); + $tableheader[$i][0]['trbgcolor'] = (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i] : null); + $tableheader[$i][$j]['x'] = $x; + $tableheader[$i][$j]['y'] = $y; + $tableheader[$i][$j]['h'] = $h; + $tableheader[$i][$j]['w'] = $w; + if (isset($cell['textbuffer'])) { + $tableheader[$i][$j]['textbuffer'] = $cell['textbuffer']; + } else { + $tableheader[$i][$j]['textbuffer'] = ''; + } + $tableheader[$i][$j]['a'] = $cell['a']; + $tableheader[$i][$j]['R'] = $cell['R']; + + $tableheader[$i][$j]['va'] = $cell['va']; + $tableheader[$i][$j]['mih'] = $cell['mih']; + $tableheader[$i][$j]['gradient'] = (isset($cell['gradient']) ? $cell['gradient'] : null); // *BACKGROUNDS* + $tableheader[$i][$j]['background-image'] = (isset($cell['background-image']) ? $cell['background-image'] : null); // *BACKGROUNDS* + $tableheader[$i][$j]['rowspan'] = (isset($cell['rowspan']) ? $cell['rowspan'] : null); + $tableheader[$i][$j]['colspan'] = (isset($cell['colspan']) ? $cell['colspan'] : null); + $tableheader[$i][$j]['bgcolor'] = $cell['bgcolor']; + + if (!$this->simpleTables) { + $tableheader[$i][$j]['border'] = $bord; + $tableheader[$i][$j]['border_details'] = $bord_det; + } elseif ($this->simpleTables) { + $tableheader[$i][$j]['border'] = $table['simple']['border']; + $tableheader[$i][$j]['border_details'] = $table['simple']['border_details']; + } + $tableheader[$i][$j]['padding'] = $cell['padding']; + if (isset($cell['direction'])) { + $tableheader[$i][$j]['direction'] = $cell['direction']; + } + if (isset($cell['cellLineHeight'])) { + $tableheader[$i][$j]['cellLineHeight'] = $cell['cellLineHeight']; + } + if (isset($cell['cellLineStackingStrategy'])) { + $tableheader[$i][$j]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy']; + } + if (isset($cell['cellLineStackingShift'])) { + $tableheader[$i][$j]['cellLineStackingShift'] = $cell['cellLineStackingShift']; + } + } + + // CELL BORDER + if ($bord) { + if ($table['borders_separate'] && $paintcell) { + $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($bord_det['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($bord_det['T']['w'] / 2), $w - $table['border_spacing_H'] - ($bord_det['L']['w'] / 2) - ($bord_det['R']['w'] / 2), $h - $table['border_spacing_V'] - ($bord_det['T']['w'] / 2) - ($bord_det['B']['w'] / 2), $bord, $bord_det, false, $table['borders_separate']); + } elseif (!$table['borders_separate']) { + $this->_tableRect($x, $y, $w, $h, $bord, $bord_det, true, $table['borders_separate']); // true causes buffer + } + } + + // VERTICAL ALIGN + if ($cell['R'] && intval($cell['R']) > 0 && intval($cell['R']) < 90 && isset($cell['va']) && $cell['va'] != 'B') { + $cell['va'] = 'B'; + } + if (!isset($cell['va']) || $cell['va'] == 'M') { + $this->y += ($h - $cell['mih']) / 2; + } elseif (isset($cell['va']) && $cell['va'] == 'B') { + $this->y += $h - $cell['mih']; + } + + // NESTED CONTENT + // TEXT (and nested tables) + + $this->divwidth = $w; + if (!empty($cell['textbuffer'])) { + $this->cellTextAlign = $align; + $this->cellLineHeight = $cell['cellLineHeight']; + $this->cellLineStackingStrategy = $cell['cellLineStackingStrategy']; + $this->cellLineStackingShift = $cell['cellLineStackingShift']; + if ($level == 1) { + if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) { + if (preg_match('/{colsum([0-9]*)[_]*}/', $cell['textbuffer'][0][0], $m)) { + $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$j]); + $cell['textbuffer'][0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $cell['textbuffer'][0][0]); + } + } elseif (!isset($table['is_thead'][$i])) { + if (isset($this->colsums[$j])) { + $this->colsums[$j] += $this->toFloat($cell['textbuffer'][0][0]); + } else { + $this->colsums[$j] = $this->toFloat($cell['textbuffer'][0][0]); + } + } + } + $opy = $this->y; + // mPDF ITERATION + if ($this->iterationCounter) { + foreach ($cell['textbuffer'] as $k => $t) { + if (preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) { + $vname = '__' . $m[1] . '_'; + if (!isset($this->$vname)) { + $this->$vname = 1; + } else { + $this->$vname++; + } + $cell['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $cell['textbuffer'][$k][0]); + } + } + } + + + if ($cell['R']) { + $cellPtSize = $cell['textbuffer'][0][11] / $this->shrin_k; + if (!$cellPtSize) { + $cellPtSize = $this->default_font_size; + } + $cellFontHeight = ($cellPtSize / Mpdf::SCALE); + $opx = $this->x; + $angle = intval($cell['R']); + // Only allow 45 to 89 degrees (when bottom-aligned) or exactly 90 or -90 + if ($angle > 90) { + $angle = 90; + } elseif ($angle > 0 && $angle < 45) { + $angle = 45; + } elseif ($angle < 0) { + $angle = -90; + } + $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight); + if (isset($cell['a']) && $cell['a'] == 'R') { + $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($cell['padding']['R'] + ($table['border_spacing_H'] / 2)); + } elseif (!isset($cell['a']) || $cell['a'] == 'C') { + $this->x += ($w / 2) + ($offset); + } else { + $this->x += ($offset) + ($cellFontHeight / 3) + ($cell['padding']['L'] + ($table['border_spacing_H'] / 2)); + } + $str = ''; + foreach ($cell['textbuffer'] as $t) { + $str .= $t[0] . ' '; + } + $str = rtrim($str); + if (!isset($cell['va']) || $cell['va'] == 'M') { + $this->y -= ($h - $cell['mih']) / 2; // Undo what was added earlier VERTICAL ALIGN + if ($angle > 0) { + $this->y += (($h - $cell['mih']) / 2) + $cell['padding']['T'] + ($cell['mih'] - ($cell['padding']['T'] + $cell['padding']['B'])); + } elseif ($angle < 0) { + $this->y += (($h - $cell['mih']) / 2) + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2)); + } + } elseif (isset($cell['va']) && $cell['va'] == 'B') { + $this->y -= $h - $cell['mih']; // Undo what was added earlier VERTICAL ALIGN + if ($angle > 0) { + $this->y += $h - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2)); + } elseif ($angle < 0) { + $this->y += $h - $cell['mih'] + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2)); + } + } elseif (isset($cell['va']) && $cell['va'] == 'T') { + if ($angle > 0) { + $this->y += $cell['mih'] - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2)); + } elseif ($angle < 0) { + $this->y += ($cell['padding']['T'] + ($table['border_spacing_V'] / 2)); + } + } + $this->Rotate($angle, $this->x, $this->y); + $s_fs = $this->FontSizePt; + $s_f = $this->FontFamily; + $s_st = $this->FontStyle; + if (!empty($cell['textbuffer'][0][3])) { // Font Color + $cor = $cell['textbuffer'][0][3]; + $this->SetTColor($cor); + } + $this->SetFont($cell['textbuffer'][0][4], $cell['textbuffer'][0][2], $cellPtSize, true, true); + + $this->magic_reverse_dir($str, $this->directionality, $cell['textbuffer'][0][18]); + $this->Text($this->x, $this->y, $str, $cell['textbuffer'][0][18], $cell['textbuffer'][0][8]); // textvar + $this->Rotate(0); + $this->SetFont($s_f, $s_st, $s_fs, true, true); + $this->SetTColor(0); + $this->x = $opx; + } else { + if (!$this->simpleTables) { + if ($bord_det) { + $btlw = $bord_det['L']['w']; + $btrw = $bord_det['R']['w']; + $bttw = $bord_det['T']['w']; + } else { + $btlw = 0; + $btrw = 0; + $bttw = 0; + } + if ($table['borders_separate']) { + $xadj = $btlw + $cell['padding']['L'] + ($table['border_spacing_H'] / 2); + $wadj = $btlw + $btrw + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H']; + $yadj = $bttw + $cell['padding']['T'] + ($table['border_spacing_H'] / 2); + } else { + $xadj = $btlw / 2 + $cell['padding']['L']; + $wadj = ($btlw + $btrw) / 2 + $cell['padding']['L'] + $cell['padding']['R']; + $yadj = $bttw / 2 + $cell['padding']['T']; + } + } elseif ($this->simpleTables) { + if ($table['borders_separate']) { // NB twice border width + $xadj = $table['simple']['border_details']['L']['w'] + $cell['padding']['L'] + ($table['border_spacing_H'] / 2); + $wadj = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H']; + $yadj = $table['simple']['border_details']['T']['w'] + $cell['padding']['T'] + ($table['border_spacing_H'] / 2); + } else { + $xadj = $table['simple']['border_details']['L']['w'] / 2 + $cell['padding']['L']; + $wadj = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w']) / 2 + $cell['padding']['L'] + $cell['padding']['R']; + $yadj = $table['simple']['border_details']['T']['w'] / 2 + $cell['padding']['T']; + } + } + $this->decimal_offset = 0; + if (substr($cell['a'], 0, 1) == 'D') { + if (isset($cell['colspan']) && $cell['colspan'] > 1) { + $this->cellTextAlign = $c['a'] = substr($cell['a'], 2, 1); + } else { + $smax = $table['decimal_align'][$j]['maxs0']; + $d_content = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1']; + $this->decimal_offset = $smax; + $extra = ($w - $d_content - $wadj); + if ($extra > 0) { + if (substr($cell['a'], 2, 1) == 'R') { + $this->decimal_offset += $extra; + } elseif (substr($cell['a'], 2, 1) == 'C') { + $this->decimal_offset += ($extra) / 2; + } + } + } + } + $this->divwidth = $w - $wadj; + if ($this->divwidth == 0) { + $this->divwidth = 0.0001; + } + $this->x += $xadj; + $this->y += $yadj; + $this->printbuffer($cell['textbuffer'], '', true, false, $cell['direction']); + } + $this->y = $opy; + } + + /* -- BACKGROUNDS -- */ + if (!$this->ColActive) { + if (isset($table['trgradients'][$i]) && ($j == 0 || $table['borders_separate'])) { + $g = $this->gradient->parseBackgroundGradient($table['trgradients'][$i]); + if ($g) { + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s]; + } else { + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } + if (isset($table['trbackground-images'][$i]) && ($j == 0 || $table['borders_separate'])) { + if (isset($table['trbackground-images'][$i]['gradient']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['trbackground-images'][$i]['gradient'])) { + $g = $this->gradient->parseMozGradient($table['trbackground-images'][$i]['gradient']); + if ($g) { + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s]; + } else { + $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + } else { + $image_id = $table['trbackground-images'][$i]['image_id']; + $orig_w = $table['trbackground-images'][$i]['orig_w']; + $orig_h = $table['trbackground-images'][$i]['orig_h']; + $x_pos = $table['trbackground-images'][$i]['x_pos']; + $y_pos = $table['trbackground-images'][$i]['y_pos']; + $x_repeat = $table['trbackground-images'][$i]['x_repeat']; + $y_repeat = $table['trbackground-images'][$i]['y_repeat']; + $resize = $table['trbackground-images'][$i]['resize']; + $opacity = $table['trbackground-images'][$i]['opacity']; + $itype = $table['trbackground-images'][$i]['itype']; + $clippath = ''; + $gx = $x0; + $gy = $y; + $gh = $h; + $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + if ($table['borders_separate']) { + $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']); + $clx = $x + ($table['border_spacing_H'] / 2); + $cly = $y + ($table['border_spacing_V'] / 2); + $clw = $w - $table['border_spacing_H']; + $clh = $h - $table['border_spacing_V']; + // Set clipping path + $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6 + $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } else { + $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } + } + } + } + + /* -- END BACKGROUNDS -- */ + + // TABLE BORDER - if separate + if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) { + $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2); + $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2); + $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2); + $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2); + $tbx = $x; + $tby = $y; + $tbw = $w; + $tbh = $h; + $tab_bord = 0; + + $corner = ''; + if ($i == 0) { // Top + $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2); + $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2); + $this->setBorder($tab_bord, Border::TOP); + $corner .= 'T'; + } + if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows)) { // Bottom + $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2); + $this->setBorder($tab_bord, Border::BOTTOM); + $corner .= 'B'; + } + if ($j == 0) { // Left + $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2); + $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2); + $this->setBorder($tab_bord, Border::LEFT); + $corner .= 'L'; + } + if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols)) { // Right + $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2); + $this->setBorder($tab_bord, Border::RIGHT); + $corner .= 'R'; + } + $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']); + } + + unset($cell); + // Reset values + $this->Reset(); + }//end of (if isset(cells)...) + }// end of columns + + $newpagestarted = false; + $this->tabletheadjustfinished = false; + + /* -- COLUMNS -- */ + if ($this->ColActive) { + if (!$this->table_keep_together && $i < $numrows - 1 && $level == 1) { + $this->breakpoints[$this->CurrCol][] = $y + $h; + } // mPDF 6 + if (count($this->cellBorderBuffer)) { + $this->printcellbuffer(); + } + } + /* -- END COLUMNS -- */ + + if ($i == $numrows - 1) { + $this->y = $y + $h; + } // last row jump (update this->y position) + if ($this->table_rotate && $level == 1) { + $this->tbrot_h += $h; + } + } // end of rows + + if (count($this->cellBorderBuffer)) { + $this->printcellbuffer(); + } + + + if ($this->tableClipPath) { + $this->writer->write("Q"); + } + $this->tableClipPath = ''; + + // Advance down page by half width of bottom border + if ($table['borders_separate']) { + $this->y += $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + } else { + $this->y += $table['max_cell_border_width']['B'] / 2; + } + + if ($table['borders_separate'] && $level == 1) { + $this->tbrot_h += $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2; + } elseif ($level == 1) { + $this->tbrot_h += $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2; + } + + $bx = $x0; + $by = $y0; + if ($table['borders_separate']) { + $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'] / 2); + if ($tablestartpageno != $this->page) { // IF broken across page + $by += $table['max_cell_border_width']['T'] / 2; + if (empty($tableheader)) { + $by -= ($table['border_spacing_V'] / 2); + } + } elseif ($split && $startrow > 0 && empty($tableheader)) { + $by -= ($table['border_spacing_V'] / 2); + } else { + $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2); + } + } elseif ($tablestartpageno != $this->page && !empty($tableheader)) { + $by += $maxbwtop / 2; + } + $by -= $tableheaderadj; + $bh = $this->y - $by; + if (!$table['borders_separate']) { + $bh -= $table['max_cell_border_width']['B'] / 2; + } + + if ($split) { + $bw = 0; + $finalSpread = true; + for ($t = $startcol; $t < $numcols; $t++) { + if ($table['colPg'][$t] == $splitpg) { + $bw += $table['wc'][$t]; + } + if ($table['colPg'][$t] > $splitpg) { + $finalSpread = false; + break; + } + } + if ($startcol == 0) { + $firstSpread = true; + } else { + $firstSpread = false; + } + if ($table['borders_separate']) { + $bw += $table['border_spacing_H']; + if ($firstSpread) { + $bw += $table['padding']['L'] + $table['border_details']['L']['w']; + } else { + $bx += ($table['padding']['L'] + $table['border_details']['L']['w']); + } + if ($finalSpread) { + $bw += $table['padding']['R'] + $table['border_details']['R']['w']; + } + } + } else { + $bw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R']; + } + + if (!$this->ColActive) { + if (isset($table['bgcolor'][-1])) { + $color = $this->colorConverter->convert($table['bgcolor'][-1], $this->PDFAXwarnings); + if ($color) { + $this->tableBackgrounds[$level * 9][] = ['gradient' => false, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'col' => $color]; + } + } + + /* -- BACKGROUNDS -- */ + if (isset($table['gradient'])) { + $g = $this->gradient->parseBackgroundGradient($table['gradient']); + if ($g) { + $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } + + if (isset($table['background-image'])) { + if (isset($table['background-image']['gradient']) && $table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'])) { + $g = $this->gradient->parseMozGradient($table['background-image']['gradient']); + if ($g) { + $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => '']; + } + } else { + $image_id = $table['background-image']['image_id']; + $orig_w = $table['background-image']['orig_w']; + $orig_h = $table['background-image']['orig_h']; + $x_pos = $table['background-image']['x_pos']; + $y_pos = $table['background-image']['y_pos']; + $x_repeat = $table['background-image']['x_repeat']; + $y_repeat = $table['background-image']['y_repeat']; + $resize = $table['background-image']['resize']; + $opacity = $table['background-image']['opacity']; + $itype = $table['background-image']['itype']; + $this->tableBackgrounds[$level * 9 + 2][] = ['x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype]; + } + } + /* -- END BACKGROUNDS -- */ + } + + if ($this->tableBackgrounds && $level == 1) { + $s = $this->PrintTableBackgrounds(); + if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) { + $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->tablebuffer); + if ($level == 1) { + $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->tablebuffer); + } + } elseif ($this->bufferoutput) { + $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->headerbuffer); + if ($level == 1) { + $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->headerbuffer); + } + } else { + $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]); + if ($level == 1) { + $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->pages[$this->page]); + } + } + $this->tableBackgrounds = []; + } + + + // TABLE BOTTOM MARGIN + if ($table['margin']['B']) { + if (!$this->table_rotate && $level == 1) { + $this->DivLn($table['margin']['B'], $this->blklvl, true); // collapsible + } else { + $this->y += ($table['margin']['B']); + } + } + + if ($this->ColActive && $level == 1) { + $this->breakpoints[$this->CurrCol][] = $this->y; + } // *COLUMNS* + + if ($split) { + // Are there more columns to print on a next page? + if ($lastCol < $numcols - 1) { + $splitpg++; + $startcol = $lastCol + 1; + return [false, $startrow, $startcol, $splitpg, $returny, $y0]; + } else { + return [true, 0, 0, 0, false, false]; + } + } + } + + // END OF FUNCTION _tableWrite() + /////////////////////////END OF TABLE CODE////////////////////////////////// + /* -- END TABLES -- */ + + function _putextgstates() + { + for ($i = 1; $i <= count($this->extgstates); $i++) { + $this->writer->object(); + $this->extgstates[$i]['n'] = $this->n; + $this->writer->write('<</Type /ExtGState'); + foreach ($this->extgstates[$i]['parms'] as $k => $v) { + $this->writer->write('/' . $k . ' ' . $v); + } + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + } + + function SetProtection($permissions = [], $user_pass = '', $owner_pass = null, $length = 40) + { + $this->encrypted = $this->protection->setProtection($permissions, $user_pass, $owner_pass, $length); + } + + // ========================================= + // FROM class PDF_Bookmark + function Bookmark($txt, $level = 0, $y = 0) + { + $txt = $this->purify_utf8_text($txt); + if ($this->text_input_as_HTML) { + $txt = $this->all_entities_to_utf8($txt); + } + if ($y == -1) { + if (!$this->ColActive) { + $y = $this->y; + } else { + $y = $this->y0; + } // If columns are on - mark top of columns + } + + // else y is used as set, or =0 i.e. top of page + // DIRECTIONALITY RTL + $bmo = ['t' => $txt, 'l' => $level, 'y' => $y, 'p' => $this->page]; + + if ($this->keep_block_together) { + // do nothing + } elseif ($this->table_rotate) { + $this->tbrot_BMoutlines[] = $bmo; + } elseif ($this->kwt) { + $this->kwt_BMoutlines[] = $bmo; + } elseif ($this->ColActive) { + $this->col_BMoutlines[] = $bmo; + } else { + $this->BMoutlines[] = $bmo; + } + } + + /** + * Initiate, and Mark a place for the Table of Contents to be inserted + */ + function TOC( + $tocfont = '', + $tocfontsize = 0, + $tocindent = 0, + $resetpagenum = '', + $pagenumstyle = '', + $suppress = '', + $toc_orientation = '', + $TOCusePaging = true, + $TOCuseLinking = false, + $toc_id = 0, + $tocoutdent = '' + ) { + + $this->tableOfContents->TOC( + $tocfont, + $tocfontsize, + $tocindent, + $resetpagenum, + $pagenumstyle, + $suppress, + $toc_orientation, + $TOCusePaging, + $TOCuseLinking, + $toc_id, + $tocoutdent + ); + } + + function TOCpagebreakByArray($a) + { + if (!is_array($a)) { + $a = []; + } + $tocoutdent = (isset($a['tocoutdent']) ? $a['tocoutdent'] : (isset($a['outdent']) ? $a['outdent'] : '')); + $TOCusePaging = (isset($a['TOCusePaging']) ? $a['TOCusePaging'] : (isset($a['paging']) ? $a['paging'] : true)); + $TOCuseLinking = (isset($a['TOCuseLinking']) ? $a['TOCuseLinking'] : (isset($a['links']) ? $a['links'] : '')); + $toc_orientation = (isset($a['toc_orientation']) ? $a['toc_orientation'] : (isset($a['toc-orientation']) ? $a['toc-orientation'] : '')); + $toc_mgl = (isset($a['toc_mgl']) ? $a['toc_mgl'] : (isset($a['toc-margin-left']) ? $a['toc-margin-left'] : '')); + $toc_mgr = (isset($a['toc_mgr']) ? $a['toc_mgr'] : (isset($a['toc-margin-right']) ? $a['toc-margin-right'] : '')); + $toc_mgt = (isset($a['toc_mgt']) ? $a['toc_mgt'] : (isset($a['toc-margin-top']) ? $a['toc-margin-top'] : '')); + $toc_mgb = (isset($a['toc_mgb']) ? $a['toc_mgb'] : (isset($a['toc-margin-bottom']) ? $a['toc-margin-bottom'] : '')); + $toc_mgh = (isset($a['toc_mgh']) ? $a['toc_mgh'] : (isset($a['toc-margin-header']) ? $a['toc-margin-header'] : '')); + $toc_mgf = (isset($a['toc_mgf']) ? $a['toc_mgf'] : (isset($a['toc-margin-footer']) ? $a['toc-margin-footer'] : '')); + $toc_ohname = (isset($a['toc_ohname']) ? $a['toc_ohname'] : (isset($a['toc-odd-header-name']) ? $a['toc-odd-header-name'] : '')); + $toc_ehname = (isset($a['toc_ehname']) ? $a['toc_ehname'] : (isset($a['toc-even-header-name']) ? $a['toc-even-header-name'] : '')); + $toc_ofname = (isset($a['toc_ofname']) ? $a['toc_ofname'] : (isset($a['toc-odd-footer-name']) ? $a['toc-odd-footer-name'] : '')); + $toc_efname = (isset($a['toc_efname']) ? $a['toc_efname'] : (isset($a['toc-even-footer-name']) ? $a['toc-even-footer-name'] : '')); + $toc_ohvalue = (isset($a['toc_ohvalue']) ? $a['toc_ohvalue'] : (isset($a['toc-odd-header-value']) ? $a['toc-odd-header-value'] : 0)); + $toc_ehvalue = (isset($a['toc_ehvalue']) ? $a['toc_ehvalue'] : (isset($a['toc-even-header-value']) ? $a['toc-even-header-value'] : 0)); + $toc_ofvalue = (isset($a['toc_ofvalue']) ? $a['toc_ofvalue'] : (isset($a['toc-odd-footer-value']) ? $a['toc-odd-footer-value'] : 0)); + $toc_efvalue = (isset($a['toc_efvalue']) ? $a['toc_efvalue'] : (isset($a['toc-even-footer-value']) ? $a['toc-even-footer-value'] : 0)); + $toc_preHTML = (isset($a['toc_preHTML']) ? $a['toc_preHTML'] : (isset($a['toc-preHTML']) ? $a['toc-preHTML'] : '')); + $toc_postHTML = (isset($a['toc_postHTML']) ? $a['toc_postHTML'] : (isset($a['toc-postHTML']) ? $a['toc-postHTML'] : '')); + $toc_bookmarkText = (isset($a['toc_bookmarkText']) ? $a['toc_bookmarkText'] : (isset($a['toc-bookmarkText']) ? $a['toc-bookmarkText'] : '')); + $resetpagenum = (isset($a['resetpagenum']) ? $a['resetpagenum'] : ''); + $pagenumstyle = (isset($a['pagenumstyle']) ? $a['pagenumstyle'] : ''); + $suppress = (isset($a['suppress']) ? $a['suppress'] : ''); + $orientation = (isset($a['orientation']) ? $a['orientation'] : ''); + $mgl = (isset($a['mgl']) ? $a['mgl'] : (isset($a['margin-left']) ? $a['margin-left'] : '')); + $mgr = (isset($a['mgr']) ? $a['mgr'] : (isset($a['margin-right']) ? $a['margin-right'] : '')); + $mgt = (isset($a['mgt']) ? $a['mgt'] : (isset($a['margin-top']) ? $a['margin-top'] : '')); + $mgb = (isset($a['mgb']) ? $a['mgb'] : (isset($a['margin-bottom']) ? $a['margin-bottom'] : '')); + $mgh = (isset($a['mgh']) ? $a['mgh'] : (isset($a['margin-header']) ? $a['margin-header'] : '')); + $mgf = (isset($a['mgf']) ? $a['mgf'] : (isset($a['margin-footer']) ? $a['margin-footer'] : '')); + $ohname = (isset($a['ohname']) ? $a['ohname'] : (isset($a['odd-header-name']) ? $a['odd-header-name'] : '')); + $ehname = (isset($a['ehname']) ? $a['ehname'] : (isset($a['even-header-name']) ? $a['even-header-name'] : '')); + $ofname = (isset($a['ofname']) ? $a['ofname'] : (isset($a['odd-footer-name']) ? $a['odd-footer-name'] : '')); + $efname = (isset($a['efname']) ? $a['efname'] : (isset($a['even-footer-name']) ? $a['even-footer-name'] : '')); + $ohvalue = (isset($a['ohvalue']) ? $a['ohvalue'] : (isset($a['odd-header-value']) ? $a['odd-header-value'] : 0)); + $ehvalue = (isset($a['ehvalue']) ? $a['ehvalue'] : (isset($a['even-header-value']) ? $a['even-header-value'] : 0)); + $ofvalue = (isset($a['ofvalue']) ? $a['ofvalue'] : (isset($a['odd-footer-value']) ? $a['odd-footer-value'] : 0)); + $efvalue = (isset($a['efvalue']) ? $a['efvalue'] : (isset($a['even-footer-value']) ? $a['even-footer-value'] : 0)); + $toc_id = (isset($a['toc_id']) ? $a['toc_id'] : (isset($a['name']) ? $a['name'] : 0)); + $pagesel = (isset($a['pagesel']) ? $a['pagesel'] : (isset($a['pageselector']) ? $a['pageselector'] : '')); + $toc_pagesel = (isset($a['toc_pagesel']) ? $a['toc_pagesel'] : (isset($a['toc-pageselector']) ? $a['toc-pageselector'] : '')); + $sheetsize = (isset($a['sheetsize']) ? $a['sheetsize'] : (isset($a['sheet-size']) ? $a['sheet-size'] : '')); + $toc_sheetsize = (isset($a['toc_sheetsize']) ? $a['toc_sheetsize'] : (isset($a['toc-sheet-size']) ? $a['toc-sheet-size'] : '')); + + $this->TOCpagebreak('', '', '', $TOCusePaging, $TOCuseLinking, $toc_orientation, $toc_mgl, $toc_mgr, $toc_mgt, $toc_mgb, $toc_mgh, $toc_mgf, $toc_ohname, $toc_ehname, $toc_ofname, $toc_efname, $toc_ohvalue, $toc_ehvalue, $toc_ofvalue, $toc_efvalue, $toc_preHTML, $toc_postHTML, $toc_bookmarkText, $resetpagenum, $pagenumstyle, $suppress, $orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $toc_id, $pagesel, $toc_pagesel, $sheetsize, $toc_sheetsize, $tocoutdent); + } + + function TOCpagebreak($tocfont = '', $tocfontsize = '', $tocindent = '', $TOCusePaging = true, $TOCuseLinking = '', $toc_orientation = '', $toc_mgl = '', $toc_mgr = '', $toc_mgt = '', $toc_mgb = '', $toc_mgh = '', $toc_mgf = '', $toc_ohname = '', $toc_ehname = '', $toc_ofname = '', $toc_efname = '', $toc_ohvalue = 0, $toc_ehvalue = 0, $toc_ofvalue = 0, $toc_efvalue = 0, $toc_preHTML = '', $toc_postHTML = '', $toc_bookmarkText = '', $resetpagenum = '', $pagenumstyle = '', $suppress = '', $orientation = '', $mgl = '', $mgr = '', $mgt = '', $mgb = '', $mgh = '', $mgf = '', $ohname = '', $ehname = '', $ofname = '', $efname = '', $ohvalue = 0, $ehvalue = 0, $ofvalue = 0, $efvalue = 0, $toc_id = 0, $pagesel = '', $toc_pagesel = '', $sheetsize = '', $toc_sheetsize = '', $tocoutdent = '') + { + // Start a new page + if ($this->state == 0) { + $this->AddPage(); + } + if ($this->y == $this->tMargin && (!$this->mirrorMargins || ($this->mirrorMargins && $this->page % 2 == 1))) { + // Don't add a page + if ($this->page == 1 && count($this->PageNumSubstitutions) == 0) { + if (!$suppress) { + $suppress = 'off'; + } + // $this->PageNumSubstitutions[] = array('from'=>1, 'reset'=> $resetpagenum, 'type'=>$pagenumstyle, 'suppress'=> $suppress); + } + $this->PageNumSubstitutions[] = ['from' => $this->page, 'reset' => $resetpagenum, 'type' => $pagenumstyle, 'suppress' => $suppress]; + } else { + $this->AddPage($orientation, 'NEXT-ODD', $resetpagenum, $pagenumstyle, $suppress, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $pagesel, $sheetsize); + } + $this->tableOfContents->TOCpagebreak($tocfont, $tocfontsize, $tocindent, $TOCusePaging, $TOCuseLinking, $toc_orientation, $toc_mgl, $toc_mgr, $toc_mgt, $toc_mgb, $toc_mgh, $toc_mgf, $toc_ohname, $toc_ehname, $toc_ofname, $toc_efname, $toc_ohvalue, $toc_ehvalue, $toc_ofvalue, $toc_efvalue, $toc_preHTML, $toc_postHTML, $toc_bookmarkText, $resetpagenum, $pagenumstyle, $suppress, $orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $toc_id, $pagesel, $toc_pagesel, $sheetsize, $toc_sheetsize, $tocoutdent); + } + + function TOC_Entry($txt, $level = 0, $toc_id = 0) + { + if ($this->ColActive) { + $ily = $this->y0; + } else { + $ily = $this->y; + } // use top of columns + + $linkn = $this->AddLink(); + $uid = '__mpdfinternallink_' . $linkn; + if ($this->table_rotate) { + $this->internallink[$uid] = ["Y" => $ily, "PAGE" => $this->page, "tbrot" => true]; + } elseif ($this->kwt) { + $this->internallink[$uid] = ["Y" => $ily, "PAGE" => $this->page, "kwt" => true]; + } elseif ($this->ColActive) { + $this->internallink[$uid] = ["Y" => $ily, "PAGE" => $this->page, "col" => $this->CurrCol]; + } elseif (!$this->keep_block_together) { + $this->internallink[$uid] = ["Y" => $ily, "PAGE" => $this->page]; + } + $this->internallink['#' . $uid] = $linkn; + $this->SetLink($linkn, $ily, $this->page); + + if (strtoupper($toc_id) == 'ALL') { + $toc_id = '_mpdf_all'; + } elseif (!$toc_id) { + $toc_id = 0; + } else { + $toc_id = strtolower($toc_id); + } + $btoc = ['t' => $txt, 'l' => $level, 'p' => $this->page, 'link' => $linkn, 'toc_id' => $toc_id]; + if ($this->keep_block_together) { + // do nothing + } /* -- TABLES -- */ elseif ($this->table_rotate) { + $this->tbrot_toc[] = $btoc; + } elseif ($this->kwt) { + $this->kwt_toc[] = $btoc; + } /* -- END TABLES -- */ elseif ($this->ColActive) { // *COLUMNS* + $this->col_toc[] = $btoc; // *COLUMNS* + } // *COLUMNS* + else { + $this->tableOfContents->_toc[] = $btoc; + } + } + + /* -- END TOC -- */ + + // ====================================================== + function MovePages($target_page, $start_page, $end_page = -1) + { + // move a page/pages EARLIER in the document + if ($end_page < 1) { + $end_page = $start_page; + } + $n_toc = $end_page - $start_page + 1; + + // Set/Update PageNumSubstitutions changes before moving anything + if (count($this->PageNumSubstitutions)) { + $tp_present = false; + $sp_present = false; + $ep_present = false; + foreach ($this->PageNumSubstitutions as $k => $v) { + if ($this->PageNumSubstitutions[$k]['from'] == $target_page) { + $tp_present = true; + if ($this->PageNumSubstitutions[$k]['suppress'] != 'on' && $this->PageNumSubstitutions[$k]['suppress'] != 1) { + $this->PageNumSubstitutions[$k]['suppress'] = 'off'; + } + } + if ($this->PageNumSubstitutions[$k]['from'] == $start_page) { + $sp_present = true; + if ($this->PageNumSubstitutions[$k]['suppress'] != 'on' && $this->PageNumSubstitutions[$k]['suppress'] != 1) { + $this->PageNumSubstitutions[$k]['suppress'] = 'off'; + } + } + if ($this->PageNumSubstitutions[$k]['from'] == ($end_page + 1)) { + $ep_present = true; + if ($this->PageNumSubstitutions[$k]['suppress'] != 'on' && $this->PageNumSubstitutions[$k]['suppress'] != 1) { + $this->PageNumSubstitutions[$k]['suppress'] = 'off'; + } + } + } + + if (!$tp_present) { + list($tp_type, $tp_suppress, $tp_reset) = $this->docPageSettings($target_page); + } + if (!$sp_present) { + list($sp_type, $sp_suppress, $sp_reset) = $this->docPageSettings($start_page); + } + if (!$ep_present) { + list($ep_type, $ep_suppress, $ep_reset) = $this->docPageSettings($start_page - 1); + } + } + + $last = []; + // store pages + for ($i = $start_page; $i <= $end_page; $i++) { + $last[] = $this->pages[$i]; + } + // move pages + for ($i = $start_page - 1; $i >= ($target_page); $i--) { + $this->pages[$i + $n_toc] = $this->pages[$i]; + } + // Put toc pages at insert point + for ($i = 0; $i < $n_toc; $i++) { + $this->pages[$target_page + $i] = $last[$i]; + } + + /* -- BOOKMARKS -- */ + // Update Bookmarks + foreach ($this->BMoutlines as $i => $o) { + if ($o['p'] >= $target_page) { + $this->BMoutlines[$i]['p'] += $n_toc; + } + } + /* -- END BOOKMARKS -- */ + + // Update Page Links + if (count($this->PageLinks)) { + $newarr = []; + foreach ($this->PageLinks as $i => $o) { + foreach ($this->PageLinks[$i] as $key => $pl) { + if (strpos($pl[4], '@') === 0) { + $p = substr($pl[4], 1); + if ($p >= $start_page && $p <= $end_page) { + $this->PageLinks[$i][$key][4] = '@' . ($p + ($target_page - $start_page)); + } elseif ($p >= $target_page && $p < $start_page) { + $this->PageLinks[$i][$key][4] = '@' . ($p + $n_toc); + } + } + } + if ($i >= $start_page && $i <= $end_page) { + $newarr[($i + ($target_page - $start_page))] = $this->PageLinks[$i]; + } elseif ($i >= $target_page && $i < $start_page) { + $newarr[($i + $n_toc)] = $this->PageLinks[$i]; + } else { + $newarr[$i] = $this->PageLinks[$i]; + } + } + $this->PageLinks = $newarr; + } + + // OrientationChanges + if (count($this->OrientationChanges)) { + $newarr = []; + foreach ($this->OrientationChanges as $p => $v) { + if ($p >= $start_page && $p <= $end_page) { + $newarr[($p + ($target_page - $start_page))] = $this->OrientationChanges[$p]; + } elseif ($p >= $target_page && $p < $start_page) { + $newarr[$p + $n_toc] = $this->OrientationChanges[$p]; + } else { + $newarr[$p] = $this->OrientationChanges[$p]; + } + } + ksort($newarr); + $this->OrientationChanges = $newarr; + } + + // Page Dimensions + if (count($this->pageDim)) { + $newarr = []; + foreach ($this->pageDim as $p => $v) { + if ($p >= $start_page && $p <= $end_page) { + $newarr[($p + ($target_page - $start_page))] = $this->pageDim[$p]; + } elseif ($p >= $target_page && $p < $start_page) { + $newarr[$p + $n_toc] = $this->pageDim[$p]; + } else { + $newarr[$p] = $this->pageDim[$p]; + } + } + ksort($newarr); + $this->pageDim = $newarr; + } + + // HTML Headers & Footers + if (count($this->saveHTMLHeader)) { + $newarr = []; + foreach ($this->saveHTMLHeader as $p => $v) { + if ($p >= $start_page && $p <= $end_page) { + $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLHeader[$p]; + } elseif ($p >= $target_page && $p < $start_page) { + $newarr[$p + $n_toc] = $this->saveHTMLHeader[$p]; + } else { + $newarr[$p] = $this->saveHTMLHeader[$p]; + } + } + ksort($newarr); + $this->saveHTMLHeader = $newarr; + } + if (count($this->saveHTMLFooter)) { + $newarr = []; + foreach ($this->saveHTMLFooter as $p => $v) { + if ($p >= $start_page && $p <= $end_page) { + $newarr[($p + ($target_page - $start_page))] = $this->saveHTMLFooter[$p]; + } elseif ($p >= $target_page && $p < $start_page) { + $newarr[$p + $n_toc] = $this->saveHTMLFooter[$p]; + } else { + $newarr[$p] = $this->saveHTMLFooter[$p]; + } + } + ksort($newarr); + $this->saveHTMLFooter = $newarr; + } + + // Update Internal Links + if (count($this->internallink)) { + foreach ($this->internallink as $key => $o) { + if (is_array($o) && $o['PAGE'] >= $start_page && $o['PAGE'] <= $end_page) { + $this->internallink[$key]['PAGE'] += ($target_page - $start_page); + } elseif (is_array($o) && $o['PAGE'] >= $target_page && $o['PAGE'] < $start_page) { + $this->internallink[$key]['PAGE'] += $n_toc; + } + } + } + + // Update Links + if (count($this->links)) { + foreach ($this->links as $key => $o) { + if ($o[0] >= $start_page && $o[0] <= $end_page) { + $this->links[$key][0] += ($target_page - $start_page); + } + if ($o[0] >= $target_page && $o[0] < $start_page) { + $this->links[$key][0] += $n_toc; + } + } + } + + // Update Form fields + if (count($this->form->forms)) { + foreach ($this->form->forms as $key => $f) { + if ($f['page'] >= $start_page && $f['page'] <= $end_page) { + $this->form->forms[$key]['page'] += ($target_page - $start_page); + } + if ($f['page'] >= $target_page && $f['page'] < $start_page) { + $this->form->forms[$key]['page'] += $n_toc; + } + } + } + + /* -- ANNOTATIONS -- */ + // Update Annotations + if (count($this->PageAnnots)) { + $newarr = []; + foreach ($this->PageAnnots as $p => $anno) { + if ($p >= $start_page && $p <= $end_page) { + $np = $p + ($target_page - $start_page); + foreach ($anno as $o) { + $newarr[$np][] = $o; + } + } elseif ($p >= $target_page && $p < $start_page) { + $np = $p + $n_toc; + foreach ($anno as $o) { + $newarr[$np][] = $o; + } + } else { + $newarr[$p] = $this->PageAnnots[$p]; + } + } + $this->PageAnnots = $newarr; + unset($newarr); + } + /* -- END ANNOTATIONS -- */ + + // Update TOC pages + if (count($this->tableOfContents->_toc)) { + foreach ($this->tableOfContents->_toc as $key => $t) { + if ($t['p'] >= $start_page && $t['p'] <= $end_page) { + $this->tableOfContents->_toc[$key]['p'] += ($target_page - $start_page); + } + if ($t['p'] >= $target_page && $t['p'] < $start_page) { + $this->tableOfContents->_toc[$key]['p'] += $n_toc; + } + } + } + + // Update PageNumSubstitutions + if (count($this->PageNumSubstitutions)) { + $newarr = []; + foreach ($this->PageNumSubstitutions as $k => $v) { + if ($this->PageNumSubstitutions[$k]['from'] >= $start_page && $this->PageNumSubstitutions[$k]['from'] <= $end_page) { + $this->PageNumSubstitutions[$k]['from'] += ($target_page - $start_page); + $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k]; + } elseif ($this->PageNumSubstitutions[$k]['from'] >= $target_page && $this->PageNumSubstitutions[$k]['from'] < $start_page) { + $this->PageNumSubstitutions[$k]['from'] += $n_toc; + $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k]; + } else { + $newarr[$this->PageNumSubstitutions[$k]['from']] = $this->PageNumSubstitutions[$k]; + } + } + + if (!$sp_present) { + $newarr[$target_page] = ['from' => $target_page, 'suppress' => $sp_suppress, 'reset' => $sp_reset, 'type' => $sp_type]; + } + if (!$tp_present) { + $newarr[($target_page + $n_toc)] = ['from' => ($target_page + $n_toc), 'suppress' => $tp_suppress, 'reset' => $tp_reset, 'type' => $tp_type]; + } + if (!$ep_present && $end_page > count($this->pages)) { + $newarr[($end_page + 1)] = ['from' => ($end_page + 1), 'suppress' => $ep_suppress, 'reset' => $ep_reset, 'type' => $ep_type]; + } + ksort($newarr); + $this->PageNumSubstitutions = []; + foreach ($newarr as $v) { + $this->PageNumSubstitutions[] = $v; + } + } + } + + function DeletePages($start_page, $end_page = -1) + { + // move a page/pages EARLIER in the document + if ($end_page < 1) { + $end_page = $start_page; + } + $n_tod = $end_page - $start_page + 1; + $last_page = count($this->pages); + $n_atend = $last_page - $end_page + 1; + + // move pages + for ($i = 0; $i < $n_atend; $i++) { + $this->pages[$start_page + $i] = $this->pages[$end_page + 1 + $i]; + } + // delete pages + for ($i = 0; $i < $n_tod; $i++) { + unset($this->pages[$last_page - $i]); + } + + + /* -- BOOKMARKS -- */ + // Update Bookmarks + foreach ($this->BMoutlines as $i => $o) { + if ($o['p'] >= $end_page) { + $this->BMoutlines[$i]['p'] -= $n_tod; + } elseif ($p < $start_page) { + unset($this->BMoutlines[$i]); + } + } + /* -- END BOOKMARKS -- */ + + // Update Page Links + if (count($this->PageLinks)) { + $newarr = []; + foreach ($this->PageLinks as $i => $o) { + foreach ($this->PageLinks[$i] as $key => $pl) { + if (strpos($pl[4], '@') === 0) { + $p = substr($pl[4], 1); + if ($p > $end_page) { + $this->PageLinks[$i][$key][4] = '@' . ($p - $n_tod); + } elseif ($p < $start_page) { + unset($this->PageLinks[$i][$key]); + } + } + } + if ($i > $end_page) { + $newarr[($i - $n_tod)] = $this->PageLinks[$i]; + } elseif ($p < $start_page) { + $newarr[$i] = $this->PageLinks[$i]; + } + } + $this->PageLinks = $newarr; + } + + // OrientationChanges + if (count($this->OrientationChanges)) { + $newarr = []; + foreach ($this->OrientationChanges as $p => $v) { + if ($p > $end_page) { + $newarr[($p - $t_tod)] = $this->OrientationChanges[$p]; + } elseif ($p < $start_page) { + $newarr[$p] = $this->OrientationChanges[$p]; + } + } + ksort($newarr); + $this->OrientationChanges = $newarr; + } + + // Page Dimensions + if (count($this->pageDim)) { + $newarr = []; + foreach ($this->pageDim as $p => $v) { + if ($p > $end_page) { + $newarr[($p - $n_tod)] = $this->pageDim[$p]; + } elseif ($p < $start_page) { + $newarr[$p] = $this->pageDim[$p]; + } + } + ksort($newarr); + $this->pageDim = $newarr; + } + + // HTML Headers & Footers + if (count($this->saveHTMLHeader)) { + foreach ($this->saveHTMLHeader as $p => $v) { + if ($p > $end_page) { + $newarr[($p - $n_tod)] = $this->saveHTMLHeader[$p]; + } // mPDF 5.7.3 + elseif ($p < $start_page) { + $newarr[$p] = $this->saveHTMLHeader[$p]; + } + } + ksort($newarr); + $this->saveHTMLHeader = $newarr; + } + if (count($this->saveHTMLFooter)) { + $newarr = []; + foreach ($this->saveHTMLFooter as $p => $v) { + if ($p > $end_page) { + $newarr[($p - $n_tod)] = $this->saveHTMLFooter[$p]; + } elseif ($p < $start_page) { + $newarr[$p] = $this->saveHTMLFooter[$p]; + } + } + ksort($newarr); + $this->saveHTMLFooter = $newarr; + } + + // Update Internal Links + foreach ($this->internallink as $key => $o) { + if ($o['PAGE'] > $end_page) { + $this->internallink[$key]['PAGE'] -= $n_tod; + } elseif ($o['PAGE'] < $start_page) { + unset($this->internallink[$key]); + } + } + + // Update Links + foreach ($this->links as $key => $o) { + if ($o[0] > $end_page) { + $this->links[$key][0] -= $n_tod; + } elseif ($o[0] < $start_page) { + unset($this->links[$key]); + } + } + + // Update Form fields + foreach ($this->form->forms as $key => $f) { + if ($f['page'] > $end_page) { + $this->form->forms[$key]['page'] -= $n_tod; + } elseif ($f['page'] < $start_page) { + unset($this->form->forms[$key]); + } + } + + /* -- ANNOTATIONS -- */ + // Update Annotations + if (count($this->PageAnnots)) { + $newarr = []; + foreach ($this->PageAnnots as $p => $anno) { + if ($p > $end_page) { + foreach ($anno as $o) { + $newarr[($p - $n_tod)][] = $o; + } + } elseif ($p < $start_page) { + $newarr[$p] = $this->PageAnnots[$p]; + } + } + ksort($newarr); + $this->PageAnnots = $newarr; + } + /* -- END ANNOTATIONS -- */ + + // Update PageNumSubstitutions + foreach ($this->PageNumSubstitutions as $k => $v) { + if ($this->PageNumSubstitutions[$k]['from'] > $end_page) { + $this->PageNumSubstitutions[$k]['from'] -= $n_tod; + } elseif ($this->PageNumSubstitutions[$k]['from'] < $start_page) { + unset($this->PageNumSubstitutions[$k]); + } + } + + unset($newarr); + $this->page = count($this->pages); + } + + // ====================================================== + /* -- INDEX -- */ + // FROM class PDF_Ref == INDEX + + function IndexEntry($txt, $xref = '') + { + if ($xref) { + $this->IndexEntrySee($txt, $xref); + return; + } + + // Search the reference (AND Ref/PageNo) in the array + $Present = false; + if ($this->keep_block_together) { + // do nothing + } /* -- TABLES -- */ elseif ($this->kwt) { + $size = count($this->kwt_Reference); + for ($i = 0; $i < $size; $i++) { + if (isset($this->kwt_Reference[$i]['t']) && $this->kwt_Reference[$i]['t'] == $txt) { + $Present = true; + if ($this->page != $this->kwt_Reference[$i]['op']) { + $this->kwt_Reference[$i]['op'] = $this->page; + } + } + } + if (!$Present) { // If not found, add it + $this->kwt_Reference[] = ['t' => $txt, 'op' => $this->page]; + } + } /* -- END TABLES -- */ else { + $size = count($this->Reference); + for ($i = 0; $i < $size; $i++) { + if (isset($this->Reference[$i]['t']) && $this->Reference[$i]['t'] == $txt) { + $Present = true; + if (!in_array($this->page, $this->Reference[$i]['p'])) { + $this->Reference[$i]['p'][] = $this->page; + } + } + } + if (!$Present) { // If not found, add it + $this->Reference[] = ['t' => $txt, 'p' => [$this->page]]; + } + } + } + + // Added function to add a reference "Elephants. See Chickens" + function IndexEntrySee($txta, $txtb) + { + if ($this->directionality == 'rtl') { // *OTL* + // ONLY DO THIS IF NOT IN TAGS + if ($txta == strip_tags($txta)) { + $txta = str_replace(':', ' - ', $txta); // *OTL* + } + if ($txtb == strip_tags($txtb)) { + $txtb = str_replace(':', ' - ', $txtb); // *OTL* + } + } // *OTL* + else { // *OTL* + if ($txta == strip_tags($txta)) { + $txta = str_replace(':', ', ', $txta); + } + if ($txtb == strip_tags($txtb)) { + $txtb = str_replace(':', ', ', $txtb); + } + } // *OTL* + $this->Reference[] = ['t' => $txta . ' - see ' . $txtb, 'p' => []]; + } + + private function filesInDir($directory) + { + $files = []; + foreach ((new \DirectoryIterator($directory)) as $v) { + if ($v->isDir() || $v->isDot()) { + continue; + } + + $files[] = $v->getPathname(); + } + + return $files; + } + + function InsertIndex($usedivletters = 1, $useLinking = false, $indexCollationLocale = '', $indexCollationGroup = '') + { + $size = count($this->Reference); + if ($size == 0) { + return false; + } + + // $spacer used after named entry + // $sep separates number [groups], $joiner joins numbers in range + // e.g. "elephant 73, 97-99" = elephant[$spacer]73[$sep]97[$joiner]99 + // $subEntrySeparator separates main and subentry (if $this->indexUseSubentries == false;) e.g. + // Mammal:elephant => Mammal[$subEntrySeparator]elephant + // $subEntryInset specifies what precedes a subentry (if $this->indexUseSubentries == true;) e.g. + // Mammal:elephant => [$subEntryInset]elephant + $spacer = "\xc2\xa0 "; + if ($this->directionality == 'rtl') { + $sep = '، '; + $joiner = '-'; + $subEntrySeparator = '، '; + $subEntryInset = ' - '; + } else { + $sep = ', '; + $joiner = '-'; + $subEntrySeparator = ', '; + $subEntryInset = ' - '; + } + + for ($i = 0; $i < $size; $i++) { + $txt = $this->Reference[$i]['t']; + $txt = strip_tags($txt); // mPDF 6 + $txt = $this->purify_utf8($txt); + $this->Reference[$i]['uf'] = $txt; // Unformatted e.g. pure utf-8 encoded characters, no mark-up/tags + // Used for ordering and collation + } + + if ($usedivletters) { + if ($indexCollationGroup && \in_array(strtolower($indexCollationGroup), array_map(function ($v) { + return strtolower(basename($v, '.php')); + }, $this->filesInDir(__DIR__ . '/../data/collations/')))) { + $collation = require __DIR__ . '/../data/collations/' . $indexCollationGroup . '.php'; + } else { + $collation = []; + } + for ($i = 0; $i < $size; $i++) { + if ($this->Reference[$i]['uf']) { + $l = mb_substr($this->Reference[$i]['uf'], 0, 1, 'UTF-8'); + if (isset($indexCollationGroup) && $indexCollationGroup) { + $uni = $this->UTF8StringToArray($l); + $ucode = $uni[0]; + if (isset($collation[$ucode])) { + $this->Reference[$i]['d'] = UtfString::code2utf($collation[$ucode]); + } else { + $this->Reference[$i]['d'] = mb_strtolower($l, 'UTF-8'); + } + } else { + $this->Reference[$i]['d'] = mb_strtolower($l, 'UTF-8'); + } + } + } + } + + // Alphabetic sort of the references + $originalLocale = setlocale(LC_COLLATE, 0); + if ($indexCollationLocale) { + setlocale(LC_COLLATE, $indexCollationLocale); + } + + usort($this->Reference, function ($a, $b) { + return strcoll(strtolower($a['uf']), strtolower($b['uf'])); + }); + + if ($indexCollationLocale) { + setlocale(LC_COLLATE, $originalLocale); + } + + $html = '<div class="mpdf_index_main">'; + + $lett = ''; + $last_lett = ''; + $mainentry = ''; + for ($i = 0; $i < $size; $i++) { + if ($this->Reference[$i]['t']) { + if ($usedivletters) { + $lett = $this->Reference[$i]['d']; + if ($lett != $last_lett) { + $html .= '<div class="mpdf_index_letter">' . $lett . '</div>'; + } + } + $txt = $this->Reference[$i]['t']; + + // Sub-entries e.g. Mammals:elephant + // But allow for tags e.g. <b>Mammal</b>:elephants + $a = preg_split('/(<.*?>)/', $txt, -1, PREG_SPLIT_DELIM_CAPTURE); + $txt = ''; + $marker = false; + foreach ($a as $k => $e) { + if ($k % 2 == 0 && !$marker) { + if (strpos($e, ':') !== false) { // == SubEntry + if ($this->indexUseSubentries) { + // If the Main entry does not have any page numbers associated with it + // create and insert an entry + list($txtmain, $sub) = preg_split('/[:]/', $e, 2); + if (strip_tags($txt . $txtmain) != $mainentry) { + $html .= '<div class="mpdf_index_entry">' . $txt . $txtmain . '</div>'; + $mainentry = strip_tags($txt . $txtmain); + } + + $txt = $subEntryInset; + $e = $sub; // Only replace first one + } else { + $e = preg_replace('/[:]/', $subEntrySeparator, $e, 1); // Only replace first one + } + $marker = true; // Don't replace any more once the subentry marker has been found + } + } + $txt .= $e; + } + + if (!$marker) { + $mainentry = strip_tags($txt); + } + + $html .= '<div class="mpdf_index_entry">'; + $html .= $txt; + $ppp = $this->Reference[$i]['p']; // = array of page numbers to point to + if (count($ppp)) { + sort($ppp); + $newarr = []; + $range_start = $ppp[0]; + $range_end = 0; + + $html .= $spacer; + + for ($zi = 1; $zi < count($ppp); $zi++) { + if ($ppp[$zi] == ($ppp[($zi - 1)] + 1)) { + $range_end = $ppp[$zi]; + } else { + if ($range_end) { + if ($range_end == $range_start + 1) { + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $range_start . '">'; + } + $html .= $this->docPageNum($range_start); + if ($useLinking) { + $html .= '</a>'; + } + $html .= $sep; + + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $ppp[$zi - 1] . '">'; + } + $html .= $this->docPageNum($ppp[$zi - 1]); + if ($useLinking) { + $html .= '</a>'; + } + $html .= $sep; + } + } else { + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $ppp[$zi - 1] . '">'; + } + $html .= $this->docPageNum($ppp[$zi - 1]); + if ($useLinking) { + $html .= '</a>'; + } + $html .= $sep; + } + $range_start = $ppp[$zi]; + $range_end = 0; + } + } + + if ($range_end) { + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $range_start . '">'; + } + $html .= $this->docPageNum($range_start); + if ($range_end == $range_start + 1) { + if ($useLinking) { + $html .= '</a>'; + } + $html .= $sep; + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $range_end . '">'; + } + $html .= $this->docPageNum($range_end); + if ($useLinking) { + $html .= '</a>'; + } + } else { + $html .= $joiner; + $html .= $this->docPageNum($range_end); + if ($useLinking) { + $html .= '</a>'; + } + } + } else { + if ($useLinking) { + $html .= '<a class="mpdf_index_link" href="@' . $ppp[(count($ppp) - 1)] . '">'; + } + $html .= $this->docPageNum($ppp[(count($ppp) - 1)]); + if ($useLinking) { + $html .= '</a>'; + } + } + } + } + $html .= '</div>'; + $last_lett = $lett; + } + $html .= '</div>'; + $save_fpb = $this->fixedPosBlockSave; + $this->WriteHTML($html); + $this->fixedPosBlockSave = $save_fpb; + + $this->breakpoints[$this->CurrCol][] = $this->y; // *COLUMNS* + } + + /* -- END INDEX -- */ + + function AcceptPageBreak() + { + if (count($this->cellBorderBuffer)) { + $this->printcellbuffer(); + } // *TABLES* + /* -- COLUMNS -- */ + if ($this->ColActive == 1) { + if ($this->CurrCol < $this->NbCol - 1) { + // Go to the next column + $this->CurrCol++; + $this->SetCol($this->CurrCol); + $this->y = $this->y0; + $this->ChangeColumn = 1; // Number (and direction) of columns changed +1, +2, -2 etc. + // DIRECTIONALITY RTL + if ($this->directionality == 'rtl') { + $this->ChangeColumn = -($this->ChangeColumn); + } // *OTL* + // Stay on the page + return false; + } else { + // Go back to the first column - NEW PAGE + if (count($this->columnbuffer)) { + $this->printcolumnbuffer(); + } + $this->SetCol(0); + $this->y0 = $this->tMargin; + $this->ChangeColumn = -($this->NbCol - 1); + // DIRECTIONALITY RTL + if ($this->directionality == 'rtl') { + $this->ChangeColumn = -($this->ChangeColumn); + } // *OTL* + // Page break + return true; + } + } /* -- END COLUMNS -- */ + /* -- TABLES -- */ elseif ($this->table_rotate) { + if ($this->tablebuffer) { + $this->printtablebuffer(); + } + return true; + } /* -- END TABLES -- */ else { // *COLUMNS* + $this->ChangeColumn = 0; + return $this->autoPageBreak; + } // *COLUMNS* + return $this->autoPageBreak; + } + + // ----------- COLUMNS --------------------- + /* -- COLUMNS -- */ + + function SetColumns($NbCol, $vAlign = '', $gap = 5) + { + // NbCol = number of columns + // Anything less than 2 turns columns off + if ($NbCol < 2) { // SET COLUMNS OFF + if ($this->ColActive) { + $this->ColActive = 0; + if (count($this->columnbuffer)) { + $this->printcolumnbuffer(); + } + $this->NbCol = 1; + $this->ResetMargins(); + $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; + $this->divwidth = 0; + $this->Ln(); + } + $this->ColActive = 0; + $this->columnbuffer = []; + $this->ColDetails = []; + $this->columnLinks = []; + $this->columnAnnots = []; + $this->columnForms = []; + $this->col_BMoutlines = []; + $this->col_toc = []; + $this->breakpoints = []; + } else { // SET COLUMNS ON + if ($this->ColActive) { + $this->ColActive = 0; + if (count($this->columnbuffer)) { + $this->printcolumnbuffer(); + } + $this->ResetMargins(); + } + if (isset($this->y) && $this->y > $this->tMargin) { + $this->Ln(); + } + $this->NbCol = $NbCol; + $this->ColGap = $gap; + $this->divwidth = 0; + $this->ColActive = 1; + $this->ColumnAdjust = true; // enables column height adjustment for the page + $this->columnbuffer = []; + $this->ColDetails = []; + $this->columnLinks = []; + $this->columnAnnots = []; + $this->columnForms = []; + $this->col_BMoutlines = []; + $this->col_toc = []; + $this->breakpoints = []; + if ((strtoupper($vAlign) == 'J') || (strtoupper($vAlign) == 'JUSTIFY')) { + $vAlign = 'J'; + } else { + $vAlign = ''; + } + $this->colvAlign = $vAlign; + // Save the ordinate + $absL = $this->DeflMargin - ($gap / 2); + $absR = $this->DefrMargin - ($gap / 2); + $PageWidth = $this->w - $absL - $absR; // virtual pagewidth for calculation only + $ColWidth = (($PageWidth - ($gap * ($NbCol))) / $NbCol); + $this->ColWidth = $ColWidth; + /* -- OTL -- */ + + if ($this->directionality == 'rtl') { + for ($i = 0; $i < $this->NbCol; $i++) { + $this->ColL[$i] = $absL + ($gap / 2) + (($NbCol - ($i + 1)) * ($PageWidth / $NbCol)); + $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos + } + } else { + /* -- END OTL -- */ + for ($i = 0; $i < $this->NbCol; $i++) { + $this->ColL[$i] = $absL + ($gap / 2) + ($i * ($PageWidth / $NbCol) ); + $this->ColR[$i] = $this->ColL[$i] + $ColWidth; // NB This is not R margin -> R pos + } + } // *OTL* + $this->pgwidth = $ColWidth; + $this->SetCol(0); + $this->y0 = $this->y; + } + $this->x = $this->lMargin; + } + + function SetCol($CurrCol) + { + // Used internally to set column by number: 0 is 1st column + // Set position on a column + $this->CurrCol = $CurrCol; + $x = $this->ColL[$CurrCol]; + $xR = $this->ColR[$CurrCol]; // NB This is not R margin -> R pos + if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN + $x += $this->MarginCorrection; + $xR += $this->MarginCorrection; + } + $this->SetMargins($x, ($this->w - $xR), $this->tMargin); + } + + function AddColumn() + { + $this->NewColumn(); + $this->ColumnAdjust = false; // disables all column height adjustment for the page. + } + + function NewColumn() + { + if ($this->ColActive == 1) { + if ($this->CurrCol < $this->NbCol - 1) { + // Go to the next column + $this->CurrCol++; + $this->SetCol($this->CurrCol); + $this->y = $this->y0; + $this->ChangeColumn = 1; + // DIRECTIONALITY RTL + if ($this->directionality == 'rtl') { + $this->ChangeColumn = -($this->ChangeColumn); + } // *OTL* + // Stay on the page + } else { + // Go back to the first column + // Page break + if (count($this->columnbuffer)) { + $this->printcolumnbuffer(); + } + $this->AddPage($this->CurOrientation); + $this->SetCol(0); + $this->y0 = $this->tMargin; + $this->ChangeColumn = -($this->NbCol - 1); + // DIRECTIONALITY RTL + if ($this->directionality == 'rtl') { + $this->ChangeColumn = -($this->ChangeColumn); + } // *OTL* + } + $this->x = $this->lMargin; + } else { + $this->AddPage($this->CurOrientation); + } + } + + function printcolumnbuffer() + { + // Columns ended (but page not ended) -> try to match all columns - unless disabled by using a custom column-break + if (!$this->ColActive && $this->ColumnAdjust && !$this->keepColumns) { + // Calculate adjustment to add to each column to calculate rel_y value + $this->ColDetails[0]['add_y'] = 0; + $last_col = 0; + // Recursively add previous column's height + for ($i = 1; $i < $this->NbCol; $i++) { + if (isset($this->ColDetails[$i]['bottom_margin']) && $this->ColDetails[$i]['bottom_margin']) { // If any entries in the column + $this->ColDetails[$i]['add_y'] = ($this->ColDetails[$i - 1]['bottom_margin'] - $this->y0) + $this->ColDetails[$i - 1]['add_y']; + $last_col = $i; // Last column actually printed + } + } + + // Calculate value for each position sensitive entry as though for one column + foreach ($this->columnbuffer as $key => $s) { + $t = $s['s']; + if ($t == 'ACROFORM') { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + $this->columnbuffer[$key]['s'] = ''; + } elseif (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } elseif (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } elseif (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } elseif (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } elseif (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } elseif (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/', $t)) { + $this->columnbuffer[$key]['rel_y'] = $s['y'] + $this->ColDetails[$s['col']]['add_y'] - $this->y0; + } + } + foreach ($this->internallink as $key => $f) { + if (is_array($f) && isset($f['col'])) { + $this->internallink[$key]['rel_y'] = $f['Y'] + $this->ColDetails[$f['col']]['add_y'] - $this->y0; + } + } + + $breaks = []; + foreach ($this->breakpoints as $c => $bpa) { + foreach ($bpa as $rely) { + $breaks[] = $rely + $this->ColDetails[$c]['add_y'] - $this->y0; + } + } + + + if (isset($this->ColDetails[$last_col]['bottom_margin'])) { + $lcbm = $this->ColDetails[$last_col]['bottom_margin']; + } else { + $lcbm = 0; + } + $sum_h = $this->ColDetails[$last_col]['add_y'] + $lcbm - $this->y0; + // $sum_h = max($this->ColDetails[$last_col]['add_y'] + $this->ColDetails[$last_col]['bottom_margin'] - $this->y0, end($breaks)); + $target_h = ($sum_h / $this->NbCol); + + $cbr = []; + for ($i = 1; $i < $this->NbCol; $i++) { + $th = ($sum_h * $i / $this->NbCol); + foreach ($breaks as $bk => $val) { + if ($val > $th) { + if (!$bk || ($val - $th) < ($th - $breaks[$bk - 1])) { + $cbr[$i - 1] = $val; + } else { + $cbr[$i - 1] = $breaks[$bk - 1]; + } + break; + } + } + } + $cbr[($this->NbCol - 1)] = $sum_h; + + // mPDF 6 + // Avoid outputing with 1st column empty + if (isset($cbr[0]) && $cbr[0] == 0) { + for ($i = 0; $i < $this->NbCol - 1; $i++) { + $cbr[$i] = $cbr[$i + 1]; + } + } + + // Now update the columns - divide into columns of approximately equal value + $last_new_col = 0; + $yadj = 0; // mm + $xadj = 0; + $last_col_bottom = 0; + $lowest_bottom_y = 0; + $block_bottom = 0; + $newcolumn = 0; + foreach ($this->columnbuffer as $key => $s) { + if (isset($s['rel_y'])) { // only process position sensitive data + if ($s['rel_y'] >= $cbr[$newcolumn]) { + $newcolumn++; + } else { + $newcolumn = $last_new_col; + } + + + $block_bottom = max($block_bottom, ($s['rel_y'] + $s['h'])); + + if ($this->directionality == 'rtl') { // *OTL* + $xadj = -(($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap)); // *OTL* + } // *OTL* + else { // *OTL* + $xadj = ($newcolumn - $s['col']) * ($this->ColWidth + $this->ColGap); + } // *OTL* + + if ($last_new_col != $newcolumn) { // Added new column + $last_col_bottom = $this->columnbuffer[$key]['rel_y']; + $block_bottom = 0; + } + $yadj = ($s['rel_y'] - $s['y']) - ($last_col_bottom) + $this->y0; + // callback function + $t = $s['s']; + + // mPDF 5.7+ + $t = $this->columnAdjustPregReplace('Td', $xadj, $yadj, '/BT (\d+\.\d\d+) (\d+\.\d\d+) Td/', $t); + $t = $this->columnAdjustPregReplace('re', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) ([\-]{0,1}\d+\.\d\d+) re/', $t); + $t = $this->columnAdjustPregReplace('l', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) l/', $t); + $t = $this->columnAdjustPregReplace('img', $xadj, $yadj, '/q (\d+\.\d\d+) 0 0 (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) cm \/(I|FO)/', $t); + $t = $this->columnAdjustPregReplace('draw', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) m/', $t); + $t = $this->columnAdjustPregReplace('bezier', $xadj, $yadj, '/(\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) (\d+\.\d\d+) c/', $t); + + $this->columnbuffer[$key]['s'] = $t; + $this->columnbuffer[$key]['newcol'] = $newcolumn; + $this->columnbuffer[$key]['newy'] = $s['y'] + $yadj; + $last_new_col = $newcolumn; + $clb = $s['y'] + $yadj + $s['h']; // bottom_margin of current + if ((isset($this->ColDetails[$newcolumn]['max_bottom']) && $clb > $this->ColDetails[$newcolumn]['max_bottom']) || (!isset($this->ColDetails[$newcolumn]['max_bottom']) && $clb)) { + $this->ColDetails[$newcolumn]['max_bottom'] = $clb; + } + if ($clb > $lowest_bottom_y) { + $lowest_bottom_y = $clb; + } + // Adjust LINKS + if (isset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->PageLinks[$this->page][$ref][0] += ($xadj * Mpdf::SCALE); + $this->PageLinks[$this->page][$ref][1] -= ($yadj * Mpdf::SCALE); + unset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]); + } + // Adjust FORM FIELDS + if (isset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->form->forms[$ref]['x'] += ($xadj); + $this->form->forms[$ref]['y'] += ($yadj); + unset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- ANNOTATIONS -- */ + if (isset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]; + if ($this->PageAnnots[$this->page][$ref]['x'] < 0) { + $this->PageAnnots[$this->page][$ref]['x'] -= ($xadj); + } else { + $this->PageAnnots[$this->page][$ref]['x'] += ($xadj); + } + $this->PageAnnots[$this->page][$ref]['y'] += ($yadj); // unlike PageLinks, Page annots has y values from top in mm + unset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- END ANNOTATIONS -- */ + } + } + + /* -- BOOKMARKS -- */ + // Adjust Bookmarks + foreach ($this->col_BMoutlines as $v) { + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $this->y0, 'p' => $v['p']]; + } + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + + // Adjust ToC + foreach ($this->col_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $v['p'], 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + $this->links[$v['link']][1] = $this->y0; + } + /* -- END TOC -- */ + + // Adjust column length to be equal + if ($this->colvAlign == 'J') { + foreach ($this->columnbuffer as $key => $s) { + if (isset($s['rel_y'])) { // only process position sensitive data + // Set ratio to expand y values or heights + if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom'] != $this->y0) { + $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0)); + } else { + $ratio = 1; + } + if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) { + $yadj = ($s['newy'] - $this->y0) * ($ratio - 1); + + // Adjust LINKS + if (isset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->PageLinks[$this->page][$ref][1] -= ($yadj * Mpdf::SCALE); // y value + $this->PageLinks[$this->page][$ref][3] *= $ratio; // height + unset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]); + } + // Adjust FORM FIELDS + if (isset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->form->forms[$ref]['x'] += ($xadj); + $this->form->forms[$ref]['y'] += ($yadj); + unset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- ANNOTATIONS -- */ + if (isset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->PageAnnots[$this->page][$ref]['y'] += ($yadj); + unset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- END ANNOTATIONS -- */ + } + } + } + foreach ($this->internallink as $key => $f) { + if (is_array($f) && isset($f['col'])) { + $last_col_bottom = 0; + for ($nbc = 0; $nbc < $this->NbCol; $nbc++) { + if ($f['rel_y'] >= $cbr[$nbc]) { + $last_col_bottom = $cbr[$nbc]; + } + } + $yadj = ($f['rel_y'] - $f['Y']) - $last_col_bottom + $this->y0; + $f['Y'] += $yadj; + unset($f['col']); + unset($f['rel_y']); + $this->internallink[$key] = $f; + } + } + + $last_col = -1; + $trans_on = false; + foreach ($this->columnbuffer as $key => $s) { + if (isset($s['rel_y'])) { // only process position sensitive data + // Set ratio to expand y values or heights + if (isset($this->ColDetails[$s['newcol']]['max_bottom']) && $this->ColDetails[$s['newcol']]['max_bottom'] && $this->ColDetails[$s['newcol']]['max_bottom'] != $this->y0) { + $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['newcol']]['max_bottom'] - ($this->y0)); + } else { + $ratio = 1; + } + if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) { + // Start Transformation + $this->pages[$this->page] .= $this->StartTransform(true) . "\n"; + $this->pages[$this->page] .= $this->transformScale(100, $ratio * 100, $x = '', $this->y0, true) . "\n"; + $trans_on = true; + } + } + // Now output the adjusted values + $this->pages[$this->page] .= $s['s'] . "\n"; + if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) { // only process position sensitive data + // Stop Transformation + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + $trans_on = false; + } + } + if ($trans_on) { + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + } + } else { // if NOT $this->colvAlign == 'J' + // Now output the adjusted values + foreach ($this->columnbuffer as $s) { + $this->pages[$this->page] .= $s['s'] . "\n"; + } + } + if ($lowest_bottom_y > 0) { + $this->y = $lowest_bottom_y; + } + } // Columns not ended but new page -> align columns (can leave the columns alone - just tidy up the height) + elseif ($this->colvAlign == 'J' && $this->ColumnAdjust && !$this->keepColumns) { + // calculate the lowest bottom margin + $lowest_bottom_y = 0; + foreach ($this->columnbuffer as $key => $s) { + // Only process output data + $t = $s['s']; + if ($t == 'ACROFORM' || (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/', $t)) || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/', $t)) || + (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/', $t)) || + (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/', $t)) || + (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/', $t)) || + (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/', $t))) { + $clb = $s['y'] + $s['h']; + if ((isset($this->ColDetails[$s['col']]['max_bottom']) && $clb > $this->ColDetails[$s['col']]['max_bottom']) || !isset($this->ColDetails[$s['col']]['max_bottom'])) { + $this->ColDetails[$s['col']]['max_bottom'] = $clb; + } + if ($clb > $lowest_bottom_y) { + $lowest_bottom_y = $clb; + } + $this->columnbuffer[$key]['rel_y'] = $s['y']; // Marks position sensitive data to process later + if ($t == 'ACROFORM') { + $this->columnbuffer[$key]['s'] = ''; + } + } + } + // Adjust column length equal + foreach ($this->columnbuffer as $key => $s) { + // Set ratio to expand y values or heights + if (isset($this->ColDetails[$s['col']]['max_bottom']) && $this->ColDetails[$s['col']]['max_bottom']) { + $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0)); + } else { + $ratio = 1; + } + if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) { + $yadj = ($s['y'] - $this->y0) * ($ratio - 1); + + // Adjust LINKS + if (isset($s['rel_y'])) { // only process position sensitive data + // otherwise triggers for all entries in column buffer (.e.g. formatting) and makes below adjustments more than once + if (isset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->PageLinks[$this->page][$ref][1] -= ($yadj * Mpdf::SCALE); // y value + $this->PageLinks[$this->page][$ref][3] *= $ratio; // height + unset($this->columnLinks[$s['col']][intval($s['x'])][intval($s['y'])]); + } + // Adjust FORM FIELDS + if (isset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->form->forms[$ref]['x'] += ($xadj); + $this->form->forms[$ref]['y'] += ($yadj); + unset($this->columnForms[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- ANNOTATIONS -- */ + if (isset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])])) { + $ref = $this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]; + $this->PageAnnots[$this->page][$ref]['y'] += ($yadj); + unset($this->columnAnnots[$s['col']][intval($s['x'])][intval($s['y'])]); + } + /* -- END ANNOTATIONS -- */ + } + } + } + + /* -- BOOKMARKS -- */ + + // Adjust Bookmarks + foreach ($this->col_BMoutlines as $v) { + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $this->y0, 'p' => $v['p']]; + } + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + + // Adjust ToC + foreach ($this->col_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $v['p'], 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + $this->links[$v['link']][1] = $this->y0; + } + /* -- END TOC -- */ + + $trans_on = false; + foreach ($this->columnbuffer as $key => $s) { + + if (isset($s['rel_y'])) { // only process position sensitive data + + // Set ratio to expand y values or heights + if (isset($this->ColDetails[$s['col']]['max_bottom']) && $this->ColDetails[$s['col']]['max_bottom']) { + $ratio = ($lowest_bottom_y - ($this->y0)) / ($this->ColDetails[$s['col']]['max_bottom'] - ($this->y0)); + } else { + $ratio = 1; + } + + if (($ratio > 1) && ($ratio <= $this->max_colH_correction)) { + // Start Transformation + $this->pages[$this->page] .= $this->StartTransform(true) . "\n"; + $this->pages[$this->page] .= $this->transformScale(100, $ratio * 100, $x = '', $this->y0, true) . "\n"; + $trans_on = true; + } + } + + // Now output the adjusted values + $this->pages[$this->page] .= $s['s'] . "\n"; + if (isset($s['rel_y']) && ($ratio > 1) && ($ratio <= $this->max_colH_correction)) { + // Stop Transformation + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + $trans_on = false; + } + } + + if ($trans_on) { + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + } + + if ($lowest_bottom_y > 0) { + $this->y = $lowest_bottom_y; + } + + } else { // Just reproduce the page as it was + + // If page has not ended but height adjustment was disabled by custom column-break - adjust y + $lowest_bottom_y = 0; + + if (!$this->ColActive && (!$this->ColumnAdjust || $this->keepColumns)) { + + // calculate the lowest bottom margin + foreach ($this->columnbuffer as $key => $s) { + + // Only process output data + $t = $s['s']; + if ($t === 'ACROFORM' + || (preg_match('/BT \d+\.\d\d+ (\d+\.\d\d+) Td/', $t)) + || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ [\-]{0,1}\d+\.\d\d+ re/', $t)) + || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) l/', $t)) + || (preg_match('/q \d+\.\d\d+ 0 0 \d+\.\d\d+ \d+\.\d\d+ (\d+\.\d\d+) cm \/(I|FO)\d+ Do Q/', $t)) + || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) m/', $t)) + || (preg_match('/\d+\.\d\d+ (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ c/', $t))) { + + $clb = $s['y'] + $s['h']; + + if (isset($this->ColDetails[$s['col']]['max_bottom']) && $clb > $this->ColDetails[$s['col']]['max_bottom'] || (!isset($this->ColDetails[$s['col']]['max_bottom']) && $clb)) { + $this->ColDetails[$s['col']]['max_bottom'] = $clb; + } + + if ($clb > $lowest_bottom_y) { + $lowest_bottom_y = $clb; + } + } + } + } + + foreach ($this->columnbuffer as $key => $s) { + if ($s['s'] != 'ACROFORM') { + $this->pages[$this->page] .= $s['s'] . "\n"; + } + } + + if ($lowest_bottom_y > 0) { + $this->y = $lowest_bottom_y; + } + + /* -- BOOKMARKS -- */ + // Output Bookmarks + foreach ($this->col_BMoutlines as $v) { + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $v['y'], 'p' => $v['p']]; + } + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + // Output ToC + foreach ($this->col_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $v['p'], 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + } + /* -- END TOC -- */ + } + + foreach ($this->internallink as $key => $f) { + + if (isset($this->internallink[$key]['col'])) { + unset($this->internallink[$key]['col']); + } + + if (isset($this->internallink[$key]['rel_y'])) { + unset($this->internallink[$key]['rel_y']); + } + } + + $this->columnbuffer = []; + $this->ColDetails = []; + $this->columnLinks = []; + $this->columnAnnots = []; + $this->columnForms = []; + + $this->col_BMoutlines = []; + $this->col_toc = []; + $this->breakpoints = []; + } + + // mPDF 5.7+ + function columnAdjustPregReplace($type, $xadj, $yadj, $pattern, $subject) + { + preg_match($pattern, $subject, $matches); + + if (!count($matches)) { + return $subject; + } + + if (!isset($matches[3])) { + $matches[3] = 0; + } + + if (!isset($matches[4])) { + $matches[4] = 0; + } + + if (!isset($matches[5])) { + $matches[5] = 0; + } + + if (!isset($matches[6])) { + $matches[6] = 0; + } + + return str_replace($matches[0], $this->columnAdjustAdd($type, Mpdf::SCALE, $xadj, $yadj, $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]), $subject); + } + /* -- END COLUMNS -- */ + + // ================================================================== + /* -- TABLES -- */ + function printcellbuffer() + { + if (count($this->cellBorderBuffer)) { + + sort($this->cellBorderBuffer); + + foreach ($this->cellBorderBuffer as $cbb) { + + $cba = unpack("A16dom/nbord/A1side/ns/dbw/a6ca/A10style/dx/dy/dw/dh/dmbl/dmbr/dmrt/dmrb/dmtl/dmtr/dmlt/dmlb/dcpd/dover/", $cbb); + $side = $cba['side']; + $color = str_pad($cba['ca'], 6, "\x00"); + + $details = []; + + $details[$side]['dom'] = (float) $cba['dom']; + $details[$side]['s'] = $cba['s']; + $details[$side]['w'] = $cba['bw']; + $details[$side]['c'] = $color; + $details[$side]['style'] = trim($cba['style']); + + $details['mbw']['BL'] = $cba['mbl']; + $details['mbw']['BR'] = $cba['mbr']; + $details['mbw']['RT'] = $cba['mrt']; + $details['mbw']['RB'] = $cba['mrb']; + $details['mbw']['TL'] = $cba['mtl']; + $details['mbw']['TR'] = $cba['mtr']; + $details['mbw']['LT'] = $cba['mlt']; + $details['mbw']['LB'] = $cba['mlb']; + + $details['cellposdom'] = $cba['cpd']; + + $details['p'] = $side; + + if ($cba['over'] == 1) { + $details[$side]['overlay'] = true; + } else { + $details[$side]['overlay'] = false; + } + + $this->_tableRect($cba['x'], $cba['y'], $cba['w'], $cba['h'], $cba['bord'], $details, false, false); + } + + $this->cellBorderBuffer = []; + } + } + + // ================================================================== + function printtablebuffer() + { + + if (!$this->table_rotate) { + + $this->pages[$this->page] .= $this->tablebuffer; + + foreach ($this->tbrot_Links as $p => $l) { + foreach ($l as $v) { + $this->PageLinks[$p][] = $v; + } + } + $this->tbrot_Links = []; + + /* -- ANNOTATIONS -- */ + foreach ($this->tbrot_Annots as $p => $l) { + foreach ($l as $v) { + $this->PageAnnots[$p][] = $v; + } + } + $this->tbrot_Annots = []; + /* -- END ANNOTATIONS -- */ + + /* -- BOOKMARKS -- */ + // Output Bookmarks + foreach ($this->tbrot_BMoutlines as $v) { + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $v['y'], 'p' => $v['p']]; + } + $this->tbrot_BMoutlines = []; + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + // Output ToC + foreach ($this->tbrot_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $v['p'], 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + } + $this->tbrot_toc = []; + /* -- END TOC -- */ + + return; + } + + // elseif rotated + $lm = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin'] + $this->blk[$this->blklvl]['border_left']['w'] + $this->blk[$this->blklvl]['padding_left']; + $pw = $this->blk[$this->blklvl]['inner_width']; + + // Start Transformation + $this->pages[$this->page] .= $this->StartTransform(true) . "\n"; + + if ($this->table_rotate > 1) { // clockwise + + if ($this->tbrot_align == 'L') { + $xadj = $this->tbrot_h; // align L (as is) + } elseif ($this->tbrot_align == 'R') { + $xadj = $lm - $this->tbrot_x0 + ($pw); // align R + } else { + $xadj = $lm - $this->tbrot_x0 + (($pw + $this->tbrot_h) / 2); // align C + } + + $yadj = 0; + + } else { // anti-clockwise + + if ($this->tbrot_align == 'L') { + $xadj = 0; // align L (as is) + } elseif ($this->tbrot_align == 'R') { + $xadj = $lm - $this->tbrot_x0 + ($pw - $this->tbrot_h); // align R + } else { + $xadj = $lm - $this->tbrot_x0 + (($pw - $this->tbrot_h) / 2); // align C + } + + $yadj = $this->tbrot_w; + } + + + $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj, true) . "\n"; + $this->pages[$this->page] .= $this->transformRotate($this->table_rotate, $this->tbrot_x0, $this->tbrot_y0, true) . "\n"; + + // Now output the adjusted values + $this->pages[$this->page] .= $this->tablebuffer; + + foreach ($this->tbrot_Links as $p => $l) { + + foreach ($l as $v) { + + $w = $v[2] / Mpdf::SCALE; + $h = $v[3] / Mpdf::SCALE; + $ax = ($v[0] / Mpdf::SCALE) - $this->tbrot_x0; + $ay = (($this->hPt - $v[1]) / Mpdf::SCALE) - $this->tbrot_y0; + + if ($this->table_rotate > 1) { // clockwise + $bx = $this->tbrot_x0 + $xadj - $ay - $h; + $by = $this->tbrot_y0 + $yadj + $ax; + } else { + $bx = $this->tbrot_x0 + $xadj + $ay; + $by = $this->tbrot_y0 + $yadj - $ax - $w; + } + + $v[0] = $bx * Mpdf::SCALE; + $v[1] = ($this->h - $by) * Mpdf::SCALE; + $v[2] = $h * Mpdf::SCALE; // swap width and height + $v[3] = $w * Mpdf::SCALE; + + $this->PageLinks[$p][] = $v; + } + } + + $this->tbrot_Links = []; + foreach ($this->internallink as $key => $f) { + if (is_array($f) && isset($f['tbrot'])) { + $f['Y'] = $this->tbrot_y0; + $f['PAGE'] = $this->page; + unset($f['tbrot']); + $this->internallink[$key] = $f; + } + } + + /* -- ANNOTATIONS -- */ + foreach ($this->tbrot_Annots as $p => $l) { + foreach ($l as $v) { + $ax = abs($v['x']) - $this->tbrot_x0; // abs because -ve values are internally set and held for reference if annotMargin set + $ay = $v['y'] - $this->tbrot_y0; + + if ($this->table_rotate > 1) { // clockwise + $bx = $this->tbrot_x0 + $xadj - $ay; + $by = $this->tbrot_y0 + $yadj + $ax; + } else { + $bx = $this->tbrot_x0 + $xadj + $ay; + $by = $this->tbrot_y0 + $yadj - $ax; + } + + if ($v['x'] < 0) { + $v['x'] = -$bx; + } else { + $v['x'] = $bx; + } + + $v['y'] = ($by); + $this->PageAnnots[$p][] = $v; + } + } + + $this->tbrot_Annots = []; + /* -- END ANNOTATIONS -- */ + + /* -- BOOKMARKS -- */ + // Adjust Bookmarks + foreach ($this->tbrot_BMoutlines as $v) { + $v['y'] = $this->tbrot_y0; + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $v['y'], 'p' => $this->page]; + } + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + // Adjust ToC - uses document page number + foreach ($this->tbrot_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $this->page, 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + $this->links[$v['link']][1] = $this->tbrot_y0; + } + /* -- END TOC -- */ + + $this->tbrot_BMoutlines = []; + $this->tbrot_toc = []; + + // Stop Transformation + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + + $this->y = $this->tbrot_y0 + $this->tbrot_w; + $this->x = $this->lMargin; + + $this->tablebuffer = ''; + } + + /** + * Keep-with-table This buffers contents of h1-6 to keep on page with table + */ + function printkwtbuffer() + { + if (!$this->kwt_moved) { + + foreach ($this->kwt_buffer as $s) { + $this->pages[$this->page] .= $s['s'] . "\n"; + } + + foreach ($this->kwt_Links as $p => $l) { + foreach ($l as $v) { + $this->PageLinks[$p][] = $v; + } + } + + $this->kwt_Links = []; + + /* -- ANNOTATIONS -- */ + foreach ($this->kwt_Annots as $p => $l) { + foreach ($l as $v) { + $this->PageAnnots[$p][] = $v; + } + } + $this->kwt_Annots = []; + /* -- END ANNOTATIONS -- */ + + /* -- INDEX -- */ + // Output Reference (index) + foreach ($this->kwt_Reference as $v) { + + $Present = 0; + + for ($i = 0; $i < count($this->Reference); $i++) { + if ($this->Reference[$i]['t'] == $v['t']) { + $Present = 1; + if (!in_array($v['op'], $this->Reference[$i]['p'])) { + $this->Reference[$i]['p'][] = $v['op']; + } + } + } + + if ($Present == 0) { + $this->Reference[] = ['t' => $v['t'], 'p' => [$v['op']]]; + } + } + $this->kwt_Reference = []; + /* -- END INDEX -- */ + + /* -- BOOKMARKS -- */ + // Output Bookmarks + foreach ($this->kwt_BMoutlines as $v) { + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $v['y'], 'p' => $v['p']]; + } + $this->kwt_BMoutlines = []; + /* -- END BOOKMARKS -- */ + + /* -- TOC -- */ + // Output ToC + foreach ($this->kwt_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $v['p'], 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + } + $this->kwt_toc = []; + /* -- END TOC -- */ + + $this->pageoutput[$this->page] = []; // mPDF 6 + + return; + } + + // Start Transformation + $this->pages[$this->page] .= $this->StartTransform(true) . "\n"; + $xadj = $this->lMargin - $this->kwt_x0; + // $yadj = $this->y - $this->kwt_y0 ; + $yadj = $this->tMargin - $this->kwt_y0; + + $this->pages[$this->page] .= $this->transformTranslate($xadj, $yadj, true) . "\n"; + + // Now output the adjusted values + foreach ($this->kwt_buffer as $s) { + $this->pages[$this->page] .= $s['s'] . "\n"; + } + + // Adjust hyperLinks + foreach ($this->kwt_Links as $p => $l) { + foreach ($l as $v) { + $bx = $this->kwt_x0 + $xadj; + $by = $this->kwt_y0 + $yadj; + $v[0] = $bx * Mpdf::SCALE; + $v[1] = ($this->h - $by) * Mpdf::SCALE; + $this->PageLinks[$p][] = $v; + } + } + + foreach ($this->internallink as $key => $f) { + if (is_array($f) && isset($f['kwt'])) { + $f['Y'] += $yadj; + $f['PAGE'] = $this->page; + unset($f['kwt']); + $this->internallink[$key] = $f; + } + } + + /* -- ANNOTATIONS -- */ + foreach ($this->kwt_Annots as $p => $l) { + foreach ($l as $v) { + $bx = $this->kwt_x0 + $xadj; + $by = $this->kwt_y0 + $yadj; + if ($v['x'] < 0) { + $v['x'] = -$bx; + } else { + $v['x'] = $bx; + } + $v['y'] = $by; + $this->PageAnnots[$p][] = $v; + } + } + /* -- END ANNOTATIONS -- */ + + /* -- BOOKMARKS -- */ + + // Adjust Bookmarks + foreach ($this->kwt_BMoutlines as $v) { + if ($v['y'] != 0) { + $v['y'] += $yadj; + } + $this->BMoutlines[] = ['t' => $v['t'], 'l' => $v['l'], 'y' => $v['y'], 'p' => $this->page]; + } + /* -- END BOOKMARKS -- */ + + /* -- INDEX -- */ + // Adjust Reference (index) + foreach ($this->kwt_Reference as $v) { + + $Present = 0; + + // Search the reference (AND Ref/PageNo) in the array + for ($i = 0; $i < count($this->Reference); $i++) { + if ($this->Reference[$i]['t'] == $v['t']) { + $Present = 1; + if (!in_array($this->page, $this->Reference[$i]['p'])) { + $this->Reference[$i]['p'][] = $this->page; + } + } + } + + if ($Present == 0) { + $this->Reference[] = ['t' => $v['t'], 'p' => [$this->page]]; + } + } + /* -- END INDEX -- */ + + /* -- TOC -- */ + + // Adjust ToC + foreach ($this->kwt_toc as $v) { + $this->tableOfContents->_toc[] = ['t' => $v['t'], 'l' => $v['l'], 'p' => $this->page, 'link' => $v['link'], 'toc_id' => $v['toc_id']]; + $this->links[$v['link']][0] = $this->page; + $this->links[$v['link']][1] += $yadj; + } + /* -- END TOC -- */ + + + $this->kwt_Links = []; + $this->kwt_Annots = []; + + $this->kwt_Reference = []; + $this->kwt_BMoutlines = []; + $this->kwt_toc = []; + + // Stop Transformation + $this->pages[$this->page] .= $this->StopTransform(true) . "\n"; + + $this->kwt_buffer = []; + + $this->y += $this->kwt_height; + $this->pageoutput[$this->page] = []; // mPDF 6 + } + /* -- END TABLES -- */ + + function printfloatbuffer() + { + if (count($this->floatbuffer)) { + $this->objectbuffer = $this->floatbuffer; + $this->printobjectbuffer(false); + $this->objectbuffer = []; + $this->floatbuffer = []; + $this->floatmargins = []; + } + } + + function Circle($x, $y, $r, $style = 'S') + { + $this->Ellipse($x, $y, $r, $r, $style); + } + + function Ellipse($x, $y, $rx, $ry, $style = 'S') + { + if ($style === 'F') { + $op = 'f'; + } elseif ($style === 'FD' or $style === 'DF') { + $op = 'B'; + } else { + $op = 'S'; + } + + $lx = 4 / 3 * (M_SQRT2 - 1) * $rx; + $ly = 4 / 3 * (M_SQRT2 - 1) * $ry; + + $h = $this->h; + + $this->writer->write(sprintf('%.3F %.3F m %.3F %.3F %.3F %.3F %.3F %.3F c', ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x + $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x - $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE)); + $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c %s', ($x + $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, $op)); + } + + /* -- DIRECTW -- */ + function AutosizeText($text, $w, $font, $style, $szfont = 72) + { + + $text = ' ' . $text . ' '; + + $this->SetFont($font, $style, $szfont, false); + + $text = $this->purify_utf8_text($text); + if ($this->text_input_as_HTML) { + $text = $this->all_entities_to_utf8($text); + } + if ($this->usingCoreFont) { + $text = mb_convert_encoding($text, $this->mb_enc, 'UTF-8'); + } + + // DIRECTIONALITY + if (preg_match("/([" . $this->pregRTLchars . "])/u", $text)) { + $this->biDirectional = true; + } + + $textvar = 0; + $save_OTLtags = $this->OTLtags; + $this->OTLtags = []; + + if ($this->useKerning) { + if ($this->CurrentFont['haskernGPOS']) { + $this->OTLtags['Plus'] .= ' kern'; + } else { + $textvar = ($textvar | TextVars::FC_KERNING); + } + } + + /* -- OTL -- */ + // Use OTL OpenType Table Layout - GSUB & GPOS + if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) { + $text = $this->otl->applyOTL($text, $this->CurrentFont['useOTL']); + $OTLdata = $this->otl->OTLdata; + } + /* -- END OTL -- */ + + $this->OTLtags = $save_OTLtags; + + $this->magic_reverse_dir($text, $this->directionality, $OTLdata); + + $width = $this->sizeConverter->convert($w); + $loop = 0; + + while ($loop == 0) { + + $this->SetFont($font, $style, $szfont, false); + $sz = $this->GetStringWidth($text, true, $OTLdata, $textvar); + + if ($sz > $w) { + $szfont --; + } else { + $loop ++; + } + } + + $this->SetFont($font, $style, $szfont, true, true); + $this->Cell($w, 0, $text, 0, 0, "C", 0, '', 0, 0, 0, 'M', 0, false, $OTLdata, $textvar); + } + /* -- END DIRECTW -- */ + + // ==================================================== + // ==================================================== + + function magic_reverse_dir(&$chunk, $dir, &$chunkOTLdata) + { + /* -- OTL -- */ + if ($this->usingCoreFont) { + return 0; + } + + if ($chunk == '') { + return 0; + } + + if ($this->biDirectional || $dir == 'rtl') { + + // check if string contains RTL text + // including any added from OTL tables (in PUA) + $pregRTLchars = $this->pregRTLchars; + + if (isset($this->CurrentFont['rtlPUAstr']) && $this->CurrentFont['rtlPUAstr']) { + $pregRTLchars .= $this->CurrentFont['rtlPUAstr']; + } + + if (!preg_match("/[" . $pregRTLchars . "]/u", $chunk) && $dir != 'rtl') { + return 0; + } // Chunk doesn't contain RTL characters + + $unicode = $this->UTF8StringToArray($chunk, false); + + $isStrong = false; + if (empty($chunkOTLdata)) { + $this->getBasicOTLdata($chunkOTLdata, $unicode, $isStrong); + } + + $useGPOS = isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0x80); + + // NB Returned $chunk may be a shorter string (with adjusted $cOTLdata) by removal of LRE, RLE etc embedding codes. + list($chunk, $rtl_content) = $this->otl->bidiSort($unicode, $chunk, $dir, $chunkOTLdata, $useGPOS); + + return $rtl_content; + } + + /* -- END OTL -- */ + return 0; + } + + /* -- OTL -- */ + + function getBasicOTLdata(&$chunkOTLdata, $unicode, &$is_strong) + { + if (empty($this->otl)) { + $this->otl = new Otl($this, $this->fontCache); + } + + $chunkOTLdata['group'] = ''; + $chunkOTLdata['GPOSinfo'] = []; + $chunkOTLdata['char_data'] = []; + + foreach ($unicode as $char) { + + $ucd_record = Ucdn::get_ucd_record($char); + $chunkOTLdata['char_data'][] = ['bidi_class' => $ucd_record[2], 'uni' => $char]; + + if ($ucd_record[2] == 0 || $ucd_record[2] == 3 || $ucd_record[2] == 4) { + $is_strong = true; + } // contains strong character + + if ($ucd_record[0] == Ucdn::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + $chunkOTLdata['group'] .= 'M'; + } elseif ($char == 32 || $char == 12288) { + $chunkOTLdata['group'] .= 'S'; + } else { + $chunkOTLdata['group'] .= 'C'; + } + } + } + + function _setBidiCodes($mode = 'start', $bdf = '') + { + $s = ''; + + if ($mode == 'end') { + + // PDF comes before PDI to close isolate-override (e.g. "LRILROPDFPDI") + if (strpos($bdf, 'PDF') !== false) { + $s .= UtfString::code2utf(0x202C); + } // POP DIRECTIONAL FORMATTING + + if (strpos($bdf, 'PDI') !== false) { + $s .= UtfString::code2utf(0x2069); + } // POP DIRECTIONAL ISOLATE + + } elseif ($mode == 'start') { + + // LRI comes before LRO to open isolate-override (e.g. "LRILROPDFPDI") + if (strpos($bdf, 'LRI') !== false) { // U+2066 LRI + $s .= UtfString::code2utf(0x2066); + } elseif (strpos($bdf, 'RLI') !== false) { // U+2067 RLI + $s .= UtfString::code2utf(0x2067); + } elseif (strpos($bdf, 'FSI') !== false) { // U+2068 FSI + $s .= UtfString::code2utf(0x2068); + } + + if (strpos($bdf, 'LRO') !== false) { // U+202D LRO + $s .= UtfString::code2utf(0x202D); + } elseif (strpos($bdf, 'RLO') !== false) { // U+202E RLO + $s .= UtfString::code2utf(0x202E); + } elseif (strpos($bdf, 'LRE') !== false) { // U+202A LRE + $s .= UtfString::code2utf(0x202A); + } elseif (strpos($bdf, 'RLE') !== false) { // U+202B RLE + $s .= UtfString::code2utf(0x202B); + } + } + + return $s; + } + /* -- END OTL -- */ + + function SetSubstitutions() + { + $subsarray = []; + require __DIR__ . '/../data/subs_win-1252.php'; + $this->substitute = []; + foreach ($subsarray as $key => $val) { + $this->substitute[UtfString::code2utf($key)] = $val; + } + } + + function SubstituteChars($html) + { + // only substitute characters between tags + if (count($this->substitute)) { + $a = preg_split('/(<.*?>)/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE); + $html = ''; + foreach ($a as $i => $e) { + if ($i % 2 == 0) { + $e = strtr($e, $this->substitute); + } + $html .= $e; + } + } + + return $html; + } + + function SubstituteCharsSIP(&$writehtml_a, &$writehtml_i, &$writehtml_e) + { + if (preg_match("/^(.*?)([\x{20000}-\x{2FFFF}]+)(.*)/u", $writehtml_e, $m)) { + if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) { + $font = $this->CurrentFont['sipext']; + if (!in_array($font, $this->available_unifonts)) { + return 0; + } + $writehtml_a[$writehtml_i] = $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, ['span style="font-family: ' . $font . '"', $m[2], '/span', $m[3]]); + $this->subPos = $writehtml_i; + return 4; + } + } + + return 0; + } + + /** + * If core font is selected in document which is not onlyCoreFonts - substitute with non-core font + */ + function SubstituteCharsNonCore(&$writehtml_a, &$writehtml_i, &$writehtml_e) + { + // Ignore if in Textarea + if ($writehtml_i > 0 && strtolower(substr($writehtml_a[$writehtml_i - 1], 0, 8)) == 'textarea') { + return 0; + } + + if (mb_convert_encoding(mb_convert_encoding($writehtml_e, $this->mb_enc, "UTF-8"), "UTF-8", $this->mb_enc) == $writehtml_e) { + return 0; + } + + $cw = &$this->CurrentFont['cw']; + $unicode = $this->UTF8StringToArray($writehtml_e, false); + $start = -1; + $end = 0; + $flag = 0; + $ftype = ''; + $u = []; + + if (!$this->subArrMB) { + + require __DIR__ . '/../data/subs_core.php'; + + $this->subArrMB['a'] = $aarr; + $this->subArrMB['s'] = $sarr; + $this->subArrMB['z'] = $zarr; + } + + foreach ($unicode as $c => $char) { + + if (($char > 127 || ($flag == 1 && $char == 32)) && $char != 173 && (!isset($this->subArrMB['a'][$char]) || ($flag == 1 && $char == 32)) && ($char < 1536 || ($char > 1791 && $char < 2304) || $char > 3455)) { + if ($flag == 0) { + $start = $c; + } + $flag = 1; + $u[] = $char; + } elseif ($flag > 0) { + $end = $c - 1; + break; + } + } + + if ($flag > 0 && !$end) { + $end = count($unicode) - 1; + } + + if ($start == -1) { + return 0; + } + + // Try in backup subs font + if (!is_array($this->backupSubsFont)) { + $this->backupSubsFont = ["$this->backupSubsFont"]; + } + + foreach ($this->backupSubsFont as $bsfctr => $bsf) { + + if ($this->fonttrans[$bsf] == 'chelvetica' || $this->fonttrans[$bsf] == 'ctimes' || $this->fonttrans[$bsf] == 'ccourier') { + continue; + } + + $font = $bsf; + unset($cw); + $cw = ''; + + if (isset($this->fonts[$font])) { + $cw = &$this->fonts[$font]['cw']; + } elseif ($this->fontCache->has($font . '.cw.dat')) { + $cw = $this->fontCache->load($font . '.cw.dat'); + } else { + $prevFontFamily = $this->FontFamily; + $prevFontStyle = $this->currentfontstyle; + $prevFontSizePt = $this->FontSizePt; + $this->SetFont($bsf, '', '', false); + $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false); + } + + if (!$cw) { + continue; + } + + $l = 0; + foreach ($u as $char) { + if ($char == 173 || $this->_charDefined($cw, $char) || ($char > 1536 && $char < 1791) || ($char > 2304 && $char < 3455 )) { + $l++; + } else { + if ($l == 0 && $bsfctr == (count($this->backupSubsFont) - 1)) { // Not found even in last backup font + $cont = mb_substr($writehtml_e, $start + 1); + $writehtml_e = mb_substr($writehtml_e, 0, $start + 1, 'UTF-8'); + array_splice($writehtml_a, $writehtml_i + 1, 0, ['', $cont]); + $this->subPos = $writehtml_i + 1; + + return 2; + } else { + break; + } + } + } + + if ($l > 0) { + $patt = mb_substr($writehtml_e, $start, $l, 'UTF-8'); + if (preg_match("/(.*?)(" . preg_quote($patt, '/') . ")(.*)/u", $writehtml_e, $m)) { + $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, ['span style="font-family: ' . $font . '"', $m[2], '/span', $m[3]]); + $this->subPos = $writehtml_i + 3; + + return 4; + } + } + } + + unset($cw); + + return 0; + } + + function SubstituteCharsMB(&$writehtml_a, &$writehtml_i, &$writehtml_e) + { + // Ignore if in Textarea + if ($writehtml_i > 0 && strtolower(substr($writehtml_a[$writehtml_i - 1], 0, 8)) == 'textarea') { + return 0; + } + + $cw = &$this->CurrentFont['cw']; + $unicode = $this->UTF8StringToArray($writehtml_e, false); + $start = -1; + $end = 0; + $flag = 0; + $ftype = ''; + $u = []; + + foreach ($unicode as $c => $char) { + + if (($flag == 0 || $flag == 2) && (!$this->_charDefined($cw, $char) || ($flag == 2 && $char == 32)) && $this->checkSIP && $char > 131071) { // Unicode Plane 2 (SIP) + + if (in_array($this->FontFamily, $this->available_CJK_fonts)) { + return 0; + } + + if ($flag == 0) { + $start = $c; + } + + $flag = 2; + $u[] = $char; + + // elseif (($flag == 0 || $flag==1) && $char != 173 && !$this->_charDefined($cw,$char) && ($char<1423 || ($char>3583 && $char < 11263))) { + + } elseif (($flag == 0 || $flag == 1) && $char != 173 && (!$this->_charDefined($cw, $char) || ($flag == 1 && $char == 32)) && ($char < 1536 || ($char > 1791 && $char < 2304) || $char > 3455)) { + + if ($flag == 0) { + $start = $c; + } + + $flag = 1; + $u[] = $char; + + } elseif ($flag > 0) { + + $end = $c - 1; + break; + + } + } + + if ($flag > 0 && !$end) { + $end = count($unicode) - 1; + } + + if ($start == -1) { + return 0; + } + + if ($flag == 2) { // SIP + + // Check if current CJK font has a ext-B related font + if (isset($this->CurrentFont['sipext']) && $this->CurrentFont['sipext']) { + $font = $this->CurrentFont['sipext']; + unset($cw); + $cw = ''; + + if (isset($this->fonts[$font])) { + $cw = &$this->fonts[$font]['cw']; + } elseif ($this->fontCache->has($font . '.cw.dat')) { + $cw = $this->fontCache->load($font . '.cw.dat'); + } else { + $prevFontFamily = $this->FontFamily; + $prevFontStyle = $this->currentfontstyle; + $prevFontSizePt = $this->FontSizePt; + $this->SetFont($font, '', '', false); + $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false); + } + + if (!$cw) { + return 0; + } + + $l = 0; + foreach ($u as $char) { + if ($this->_charDefined($cw, $char) || $char > 131071) { + $l++; + } else { + break; + } + } + + if ($l > 0) { + $patt = mb_substr($writehtml_e, $start, $l); + if (preg_match("/(.*?)(" . preg_quote($patt, '/') . ")(.*)/u", $writehtml_e, $m)) { + $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, ['span style="font-family: ' . $font . '"', $m[2], '/span', $m[3]]); + $this->subPos = $writehtml_i + 3; + return 4; + } + } + } + + // Check Backup SIP font (defined in Config\FontVariables) + if (isset($this->backupSIPFont) && $this->backupSIPFont) { + + if ($this->currentfontfamily != $this->backupSIPFont) { + $font = $this->backupSIPFont; + } else { + unset($cw); + return 0; + } + + unset($cw); + $cw = ''; + + if (isset($this->fonts[$font])) { + $cw = &$this->fonts[$font]['cw']; + } elseif ($this->fontCache->has($font . '.cw.dat')) { + $cw = $this->fontCache->load($font . '.cw.dat'); + } else { + $prevFontFamily = $this->FontFamily; + $prevFontStyle = $this->currentfontstyle; + $prevFontSizePt = $this->FontSizePt; + $this->SetFont($this->backupSIPFont, '', '', false); + $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false); + } + + if (!$cw) { + return 0; + } + + $l = 0; + foreach ($u as $char) { + if ($this->_charDefined($cw, $char) || $char > 131071) { + $l++; + } else { + break; + } + } + + if ($l > 0) { + $patt = mb_substr($writehtml_e, $start, $l); + if (preg_match("/(.*?)(" . preg_quote($patt, '/') . ")(.*)/u", $writehtml_e, $m)) { + $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, ['span style="font-family: ' . $font . '"', $m[2], '/span', $m[3]]); + $this->subPos = $writehtml_i + 3; + return 4; + } + } + } + + return 0; + } + + // FIRST TRY CORE FONTS (when appropriate) + if (!$this->PDFA && !$this->PDFX && !$this->biDirectional) { // mPDF 6 + $repl = []; + if (!$this->subArrMB) { + require __DIR__ . '/../data/subs_core.php'; + $this->subArrMB['a'] = $aarr; + $this->subArrMB['s'] = $sarr; + $this->subArrMB['z'] = $zarr; + } + if (isset($this->subArrMB['a'][$u[0]])) { + $font = 'tta'; + $ftype = 'C'; + foreach ($u as $char) { + if (isset($this->subArrMB['a'][$char])) { + $repl[] = $this->subArrMB['a'][$char]; + } else { + break; + } + } + } elseif (isset($this->subArrMB['z'][$u[0]])) { + $font = 'ttz'; + $ftype = 'C'; + foreach ($u as $char) { + if (isset($this->subArrMB['z'][$char])) { + $repl[] = $this->subArrMB['z'][$char]; + } else { + break; + } + } + } elseif (isset($this->subArrMB['s'][$u[0]])) { + $font = 'tts'; + $ftype = 'C'; + foreach ($u as $char) { + if (isset($this->subArrMB['s'][$char])) { + $repl[] = $this->subArrMB['s'][$char]; + } else { + break; + } + } + } + if ($ftype == 'C') { + $patt = mb_substr($writehtml_e, $start, count($repl)); + if (preg_match("/(.*?)(" . preg_quote($patt, '/') . ")(.*)/u", $writehtml_e, $m)) { + $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, [$font, implode('|', $repl), '/' . $font, $m[3]]); // e.g. <tts> + $this->subPos = $writehtml_i + 3; + return 4; + } + return 0; + } + } + + // LASTLY TRY IN BACKUP SUBS FONT + if (!is_array($this->backupSubsFont)) { + $this->backupSubsFont = ["$this->backupSubsFont"]; + } + + foreach ($this->backupSubsFont as $bsfctr => $bsf) { + if ($this->currentfontfamily != $bsf) { + $font = $bsf; + } else { + continue; + } + + unset($cw); + $cw = ''; + + if (isset($this->fonts[$font])) { + $cw = &$this->fonts[$font]['cw']; + } elseif ($this->fontCache->has($font . '.cw.dat')) { + $cw = $this->fontCache->load($font . '.cw.dat'); + } else { + $prevFontFamily = $this->FontFamily; + $prevFontStyle = $this->currentfontstyle; + $prevFontSizePt = $this->FontSizePt; + $this->SetFont($bsf, '', '', false); + $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt, false); + if ($this->fontCache->has($font . '.cw.dat')) { + $cw = $this->fontCache->load($font . '.cw.dat'); + } + } + + if (!$cw) { + continue; + } + + $l = 0; + foreach ($u as $char) { + if ($char == 173 || $this->_charDefined($cw, $char) || ($char > 1536 && $char < 1791) || ($char > 2304 && $char < 3455 )) { // Arabic and Indic + $l++; + } else { + if ($l == 0 && $bsfctr == (count($this->backupSubsFont) - 1)) { // Not found even in last backup font + $cont = mb_substr($writehtml_e, $start + 1); + $writehtml_e = mb_substr($writehtml_e, 0, $start + 1); + array_splice($writehtml_a, $writehtml_i + 1, 0, ['', $cont]); + $this->subPos = $writehtml_i + 1; + return 2; + } else { + break; + } + } + } + + if ($l > 0) { + $patt = mb_substr($writehtml_e, $start, $l); + if (preg_match("/(.*?)(" . preg_quote($patt, '/') . ")(.*)/u", $writehtml_e, $m)) { + $writehtml_e = $m[1]; + array_splice($writehtml_a, $writehtml_i + 1, 0, ['span style="font-family: ' . $font . '"', $m[2], '/span', $m[3]]); + $this->subPos = $writehtml_i + 3; + return 4; + } + } + } + + unset($cw); + + return 0; + } + + function setHiEntitySubstitutions() + { + $entarr = include __DIR__ . '/../data/entity_substitutions.php'; + + foreach ($entarr as $key => $val) { + $this->entsearch[] = '&' . $key . ';'; + $this->entsubstitute[] = UtfString::code2utf($val); + } + } + + function SubstituteHiEntities($html) + { + // converts html_entities > ASCII 127 to unicode + // Leaves in particular < to distinguish from tag marker + if (count($this->entsearch)) { + $html = str_replace($this->entsearch, $this->entsubstitute, $html); + } + + return $html; + } + + /** + * Edited v1.2 Pass by reference; option to continue if invalid UTF-8 chars + */ + function is_utf8(&$string) + { + if ($string === mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32")) { + return true; + } + + if ($this->ignore_invalid_utf8) { + $string = mb_convert_encoding(mb_convert_encoding($string, "UTF-32", "UTF-8"), "UTF-8", "UTF-32"); + return true; + } + + return false; + } + + /** + * For HTML + * + * Checks string is valid UTF-8 encoded + * converts html_entities > ASCII 127 to UTF-8 + * Only exception - leaves low ASCII entities e.g. < & etc. + * Leaves in particular < to distinguish from tag marker + */ + function purify_utf8($html, $lo = true) + { + if (!$this->is_utf8($html)) { + + while (mb_convert_encoding(mb_convert_encoding($html, "UTF-32", "UTF-8"), "UTF-8", "UTF-32") !== $html) { + + $a = @iconv('UTF-8', 'UTF-8', $html); + $error = error_get_last(); + if ($error && $error['message'] === 'iconv(): Detected an illegal character in input string') { + throw new \Mpdf\MpdfException('Invalid input characters. Did you set $mpdf->in_charset properly?'); + } + + $pos = $start = strlen($a); + $err = ''; + while (ord(substr($html, $pos, 1)) > 128) { + $err .= '[[#' . ord(substr($html, $pos, 1)) . ']]'; + $pos++; + } + + $this->logger->error($err, ['context' => LogContext::UTF8]); + $html = substr($html, $pos); + } + + throw new \Mpdf\MpdfException("HTML contains invalid UTF-8 character(s). See log for further details"); + } + + $html = preg_replace("/\r/", "", $html); + + // converts html_entities > ASCII 127 to UTF-8 + // Leaves in particular < to distinguish from tag marker + $html = $this->SubstituteHiEntities($html); + + // converts all &#nnn; or &#xHHH; to UTF-8 multibyte + // If $lo==true then includes ASCII < 128 + $html = UtfString::strcode2utf($html, $lo); + + return $html; + } + + /** + * For TEXT + */ + function purify_utf8_text($txt) + { + // Make sure UTF-8 string of characters + if (!$this->is_utf8($txt)) { + throw new \Mpdf\MpdfException("Text contains invalid UTF-8 character(s)"); + } + + $txt = preg_replace("/\r/", "", $txt); + + return ($txt); + } + + function all_entities_to_utf8($txt) + { + // converts txt_entities > ASCII 127 to UTF-8 + // Leaves in particular < to distinguish from tag marker + $txt = $this->SubstituteHiEntities($txt); + + // converts all &#nnn; or &#xHHH; to UTF-8 multibyte + $txt = UtfString::strcode2utf($txt); + + $txt = $this->lesser_entity_decode($txt); + return ($txt); + } + + /* -- BARCODES -- */ + /** + * UPC/EAN barcode + * + * EAN13, EAN8, UPCA, UPCE, ISBN, ISSN + * Accepts 12 or 13 digits with or without - hyphens + */ + function WriteBarcode($code, $showtext = 1, $x = '', $y = '', $size = 1, $border = 0, $paddingL = 1, $paddingR = 1, $paddingT = 2, $paddingB = 2, $height = 1, $bgcol = false, $col = false, $btype = 'ISBN', $supplement = '0', $supplement_code = '', $k = 1) + { + if (empty($code)) { + return; + } + + $codestr = $code; + $code = preg_replace('/\-/', '', $code); + + $this->barcode = new Barcode(); + if ($btype == 'ISSN' || $btype == 'ISBN') { + $arrcode = $this->barcode->getBarcodeArray($code, 'EAN13'); + } else { + $arrcode = $this->barcode->getBarcodeArray($code, $btype); + } + + if ($arrcode === false) { + throw new \Mpdf\MpdfException('Error in barcode string: ' . $codestr); + } + + if ((($btype === 'EAN13' || $btype === 'ISBN' || $btype === 'ISSN') && strlen($code) === 12) + || ($btype == 'UPCA' && strlen($code) === 11) + || ($btype == 'UPCE' && strlen($code) === 11) + || ($btype == 'EAN8' && strlen($code) === 7)) { + + $code .= $arrcode['checkdigit']; + + if (stristr($codestr, '-')) { + $codestr .= '-' . $arrcode['checkdigit']; + } else { + $codestr .= $arrcode['checkdigit']; + } + } + + if ($btype === 'ISBN') { + $codestr = 'ISBN ' . $codestr; + } + + if ($btype === 'ISSN') { + $codestr = 'ISSN ' . $codestr; + } + + if (empty($x)) { + $x = $this->x; + } + + if (empty($y)) { + $y = $this->y; + } + + // set foreground color + $prevDrawColor = $this->DrawColor; + $prevTextColor = $this->TextColor; + $prevFillColor = $this->FillColor; + + $lw = $this->LineWidth; + $this->SetLineWidth(0.01); + + $size /= $k; // in case resized in a table + + $xres = $arrcode['nom-X'] * $size; + $llm = $arrcode['lightmL'] * $arrcode['nom-X'] * $size; // Left Light margin + $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin + + $bcw = ($arrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size + + $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins + $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding + + $fbwi = $fbw - 2; // Full barcode width incl. light margins - 2mm - for isbn string + // cf. http://www.gs1uk.org/downloads/bar_code/Bar coding getting it right.pdf + $num_height = 3 * $size; // Height of numerals + $fbh = $arrcode['nom-H'] * $size * $height; // Full barcode height incl. numerals + $bch = $fbh - (1.5 * $size); // Barcode height of bars (3mm for numerals) + + if (($btype == 'EAN13' && $showtext) || $btype == 'ISSN' || $btype == 'ISBN') { // Add height for ISBN string + margin from top of bars + $tisbnm = 1.5 * $size; // Top margin between isbn (if shown) & bars + $codestr_fontsize = 2.1 * $size; + $paddingT += $codestr_fontsize + $tisbnm; + } + + $oh = $fbh + $paddingT + $paddingB; // Full overall height incl. user-defined padding + + // PRINT border background color + $xpos = $x; + $ypos = $y; + + if ($col) { + $this->SetDColor($col); + $this->SetTColor($col); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + + if ($bgcol) { + $this->SetFColor($bgcol); + } else { + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + } + + if (!$bgcol && !$col) { // fn. called directly - not via HTML + + if ($border) { + $fillb = 'DF'; + } else { + $fillb = 'F'; + } + + $this->Rect($xpos, $ypos, $ow, $oh, $fillb); + } + + + // PRINT BARS + $xpos = $x + $paddingL + $llm; + $ypos = $y + $paddingT; + + if ($col) { + $this->SetFColor($col); + } else { + $this->SetFColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + + if ($arrcode !== false) { + foreach ($arrcode["bcode"] as $v) { + $bw = ($v["w"] * $xres); + if ($v["t"]) { + // draw a vertical bar + $this->Rect($xpos, $ypos, $bw, $bch, 'F'); + } + $xpos += $bw; + } + } + + // print text + $prevFontFamily = $this->FontFamily; + $prevFontStyle = $this->FontStyle; + $prevFontSizePt = $this->FontSizePt; + + // ISBN string + if (($btype === 'EAN13' && $showtext) || $btype === 'ISBN' || $btype === 'ISSN') { + + if ($this->onlyCoreFonts) { + $this->SetFont('chelvetica'); + } else { + $this->SetFont('sans'); + } + + if ($bgcol) { + $this->SetFColor($bgcol); + } else { + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + } + + $this->x = $x + $paddingL + 1; // 1mm left margin (cf. $fbwi above) + + // max width is $fbwi + $loop = 0; + while ($loop == 0) { + $this->SetFontSize($codestr_fontsize * 1.4 * Mpdf::SCALE, false); // don't write + $sz = $this->GetStringWidth($codestr); + + if ($sz > $fbwi) { + $codestr_fontsize -= 0.1; + } else { + $loop ++; + } + } + + $this->SetFont('', '', $codestr_fontsize * 1.4 * Mpdf::SCALE, true, true); // * 1.4 because font height is only 7/10 of given mm + // WORD SPACING + if ($fbwi > $sz) { + $xtra = $fbwi - $sz; + $charspacing = $xtra / (strlen($codestr) - 1); + if ($charspacing) { + $this->writer->write(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE)); + } + } + + $this->y = $y + $paddingT - ($codestr_fontsize ) - $tisbnm; + $this->Cell($fbw, $codestr_fontsize, $codestr); + + if ($charspacing) { + $this->writer->write('BT 0 Tc ET'); + } + } + + + // Bottom NUMERALS + // mPDF 5.7.4 + if ($this->onlyCoreFonts) { + $this->SetFont('ccourier'); + $fh = 1.3; + } else { + $this->SetFont('ocrb'); + $fh = 1.06; + } + + $charRO = ''; + + if ($btype === 'EAN13' || $btype === 'ISBN' || $btype === 'ISSN') { + + $outerfontsize = 3; // Inner fontsize = 3 + $outerp = $xres * 4; + $innerp = $xres * 2.5; + $textw = ($bcw * 0.5) - $outerp - $innerp; + $chars = 6; // number of numerals in each half + $charLO = substr($code, 0, 1); // Left Outer + $charLI = substr($code, 1, 6); // Left Inner + $charRI = substr($code, 7, 6); // Right Inner + + if (!$supplement) { + $charRO = '>'; // Right Outer + } + + } elseif ($btype === 'UPCA') { + + $outerfontsize = 2.3; // Inner fontsize = 3 + $outerp = $xres * 10; + $innerp = $xres * 2.5; + $textw = ($bcw * 0.5) - $outerp - $innerp; + $chars = 5; + $charLO = substr($code, 0, 1); // Left Outer + $charLI = substr($code, 1, 5); // Left Inner + $charRI = substr($code, 6, 5); // Right Inner + $charRO = substr($code, 11, 1); // Right Outer + + } elseif ($btype === 'UPCE') { + + $outerfontsize = 2.3; // Inner fontsize = 3 + $outerp = $xres * 4; + $innerp = 0; + $textw = ($bcw * 0.5) - $outerp - $innerp; + $chars = 3; + $upce_code = $arrcode['code']; + $charLO = substr($code, 0, 1); // Left Outer + $charLI = substr($upce_code, 0, 3); // Left Inner + $charRI = substr($upce_code, 3, 3); // Right Inner + $charRO = substr($code, 11, 1); // Right Outer + + } elseif ($btype === 'EAN8') { + + $outerfontsize = 3; // Inner fontsize = 3 + $outerp = $xres * 4; + $innerp = $xres * 2.5; + $textw = ($bcw * 0.5) - $outerp - $innerp; + $chars = 4; + $charLO = '<'; // Left Outer + $charLI = substr($code, 0, 4); // Left Inner + $charRI = substr($code, 4, 4); // Right Inner + + if (!$supplement) { + $charRO = '>'; // Right Outer + } + } + + $this->SetFontSize(($outerfontsize / 3) * 3 * $fh * $size * Mpdf::SCALE); // 3mm numerals (FontSize is larger to account for space above/below characters) + + if (!$this->usingCoreFont) { // character width at 3mm + $cw = $this->_getCharWidth($this->CurrentFont['cw'], 32) * 3 * $fh * $size / 1000; + } else { + $cw = 600 * 3 * $fh * $size / 1000; + } + + // Outer left character + $y_text = $y + $paddingT + $bch - ($num_height / 2); + $y_text_outer = $y + $paddingT + $bch - ($num_height * ($outerfontsize / 3) / 2); + + $this->x = $x + $paddingL - ($cw * ($outerfontsize / 3) * 0.1); // 0.1 is correction as char does not fill full width; + $this->y = $y_text_outer; + $this->Cell($cw, $num_height, $charLO); + + // WORD SPACING for inner chars + $xtra = $textw - ($cw * $chars); + $charspacing = $xtra / ($chars - 1); + if ($charspacing) { + $this->writer->write(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE)); + } + + if ($bgcol) { + $this->SetFColor($bgcol); + } else { + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + } + + $this->SetFontSize(3 * $fh * $size * Mpdf::SCALE); // 3mm numerals (FontSize is larger to account for space above/below characters) + + // Inner left half characters + $this->x = $x + $paddingL + $llm + $outerp; + $this->y = $y_text; + $this->Cell($textw, $num_height, $charLI, 0, 0, '', 1); + + // Inner right half characters + $this->x = $x + $paddingL + $llm + ($bcw * 0.5) + $innerp; + $this->y = $y_text; + $this->Cell($textw, $num_height, $charRI, 0, 0, '', 1); + + if ($charspacing) { + $this->writer->write('BT 0 Tc ET'); + } + + // Outer Right character + $this->SetFontSize(($outerfontsize / 3) * 3 * $fh * $size * Mpdf::SCALE); // 3mm numerals (FontSize is larger to account for space above/below characters) + + $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw * ($outerfontsize / 3) * 0.9); // 0.9 is correction as char does not fill full width + $this->y = $y_text_outer; + $this->Cell($cw * ($outerfontsize / 3), $num_height, $charRO, 0, 0, 'R'); + + if ($supplement) { // EAN-2 or -5 Supplement + // PRINT BARS + $supparrcode = $this->barcode->getBarcodeArray($supplement_code, 'EAN' . $supplement); + + if ($supparrcode === false) { + throw new \Mpdf\MpdfException('Error in barcode string (supplement): ' . $codestr . ' ' . $supplement_code); + } + + if (strlen($supplement_code) != $supplement) { + throw new \Mpdf\MpdfException('Barcode supplement incorrect: ' . $supplement_code); + } + + $llm = $fbw - (($arrcode['lightmR'] - $supparrcode['sepM']) * $arrcode['nom-X'] * $size); // Left Light margin + $rlm = $arrcode['lightmR'] * $arrcode['nom-X'] * $size; // Right Light margin + + $bcw = ($supparrcode["maxw"] * $xres); // Barcode width = Should always be 31.35mm * $size + + $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins + $ow = $fbw + $paddingL + $paddingR; // Full overall width incl. user-defined padding + $bch = $fbh - (1.5 * $size) - ($num_height + 0.5); // Barcode height of bars (3mm for numerals) + + $xpos = $x + $paddingL + $llm; + $ypos = $y + $paddingT + $num_height + 0.5; + + if ($col) { + $this->SetFColor($col); + } else { + $this->SetFColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + + if ($supparrcode !== false) { + foreach ($supparrcode["bcode"] as $v) { + $bw = ($v["w"] * $xres); + if ($v["t"]) { + // draw a vertical bar + $this->Rect($xpos, $ypos, $bw, $bch, 'F'); + } + $xpos += $bw; + } + } + + // Characters + if ($bgcol) { + $this->SetFColor($bgcol); + } else { + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + } + + $this->SetFontSize(3 * $fh * $size * Mpdf::SCALE); // 3mm numerals (FontSize is larger to account for space above/below characters) + $this->x = $x + $paddingL + $llm; + $this->y = $y + $paddingT; + $this->Cell($bcw, $num_height, $supplement_code, 0, 0, 'C'); + + // Outer Right character (light margin) + $this->SetFontSize(($outerfontsize / 3) * 3 * $fh * $size * Mpdf::SCALE); // 3mm numerals (FontSize is larger to account for space above/below characters) + $this->x = $x + $paddingL + $llm + $bcw + $rlm - ($cw * 0.9); // 0.9 is correction as char does not fill full width + $this->y = $y + $paddingT; + $this->Cell($cw * ($outerfontsize / 3), $num_height, '>', 0, 0, 'R'); + } + + // Restore ************** + $this->SetFont($prevFontFamily, $prevFontStyle, $prevFontSizePt); + $this->DrawColor = $prevDrawColor; + $this->TextColor = $prevTextColor; + $this->FillColor = $prevFillColor; + $this->SetLineWidth($lw); + $this->SetY($y); + } + + /** + * POSTAL and OTHER barcodes + */ + function WriteBarcode2($code, $x = '', $y = '', $size = 1, $height = 1, $bgcol = false, $col = false, $btype = 'IMB', $print_ratio = '', $k = 1, $quiet_zone_left = null, $quiet_zone_right = null) + { + if (empty($code)) { + return; + } + + $this->barcode = new Barcode(); + $arrcode = $this->barcode->getBarcodeArray($code, $btype, $print_ratio, $quiet_zone_left, $quiet_zone_right); + + if (empty($x)) { + $x = $this->x; + } + + if (empty($y)) { + $y = $this->y; + } + + $prevDrawColor = $this->DrawColor; + $prevTextColor = $this->TextColor; + $prevFillColor = $this->FillColor; + $lw = $this->LineWidth; + $this->SetLineWidth(0.01); + $size /= $k; // in case resized in a table + $xres = $arrcode['nom-X'] * $size; + + if ($btype === 'IMB' || $btype === 'RM4SCC' || $btype === 'KIX' || $btype === 'POSTNET' || $btype === 'PLANET') { + $llm = $arrcode['quietL'] / $k; // Left Quiet margin + $rlm = $arrcode['quietR'] / $k; // Right Quiet margin + $tlm = $blm = $arrcode['quietTB'] / $k; + $height = 1; // Overrides + } elseif (in_array($btype, ['C128A', 'C128B', 'C128C', 'C128RAW', 'EAN128A', 'EAN128B', 'EAN128C', 'C39', 'C39+', 'C39E', 'C39E+', 'S25', 'S25+', 'I25', 'I25+', 'I25B', 'I25B+', 'C93', 'MSI', 'MSI+', 'CODABAR', 'CODE11'])) { + $llm = $arrcode['lightmL'] * $xres; // Left Quiet margin + $rlm = $arrcode['lightmR'] * $xres; // Right Quiet margin + $tlm = $blm = $arrcode['lightTB'] * $xres * $height; + } + + $bcw = ($arrcode["maxw"] * $xres); + $fbw = $bcw + $llm + $rlm; // Full barcode width incl. light margins + + $bch = ($arrcode["nom-H"] * $size * $height); + $fbh = $bch + $tlm + $blm; // Full barcode height + + // PRINT border background color + $xpos = $x; + $ypos = $y; + + if ($col) { + $this->SetDColor($col); + $this->SetTColor($col); + } else { + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + + if ($bgcol) { + $this->SetFColor($bgcol); + } else { + $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings)); + } + + // PRINT BARS + if ($col) { + $this->SetFColor($col); + } else { + $this->SetFColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + } + $xpos = $x + $llm; + + if ($arrcode !== false) { + foreach ($arrcode["bcode"] as $v) { + $bw = ($v["w"] * $xres); + if ($v["t"]) { + $ypos = $y + $tlm + ($bch * $v['p'] / $arrcode['maxh']); + $this->Rect($xpos, $ypos, $bw, ($v['h'] * $bch / $arrcode['maxh']), 'F'); + } + $xpos += $bw; + } + } + + // PRINT BEARER BARS + if ($btype == 'I25B' || $btype == 'I25B+') { + $this->Rect($x, $y, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F'); + $this->Rect($x, $y + $tlm + $bch, $fbw, ($arrcode['lightTB'] * $xres * $height), 'F'); + } + + // Restore ************** + $this->DrawColor = $prevDrawColor; + $this->TextColor = $prevTextColor; + $this->FillColor = $prevFillColor; + $this->SetLineWidth($lw); + $this->SetY($y); + } + /* -- END BARCODES -- */ + + function StartTransform($returnstring = false) + { + if ($returnstring) { + return('q'); + } else { + $this->writer->write('q'); + } + } + + function StopTransform($returnstring = false) + { + if ($returnstring) { + return('Q'); + } else { + $this->writer->write('Q'); + } + } + + function transformScale($s_x, $s_y, $x = '', $y = '', $returnstring = false) + { + if ($x === '') { + $x = $this->x; + } + + if ($y === '') { + $y = $this->y; + } + + if (($s_x == 0) or ( $s_y == 0)) { + throw new \Mpdf\MpdfException('Please do not use values equal to zero for scaling'); + } + + $y = ($this->h - $y) * Mpdf::SCALE; + $x *= Mpdf::SCALE; + + // calculate elements of transformation matrix + $s_x /= 100; + $s_y /= 100; + $tm = []; + $tm[0] = $s_x; + $tm[1] = 0; + $tm[2] = 0; + $tm[3] = $s_y; + $tm[4] = $x * (1 - $s_x); + $tm[5] = $y * (1 - $s_y); + + // scale the coordinate system + if ($returnstring) { + return($this->_transform($tm, true)); + } else { + $this->_transform($tm); + } + } + + function transformTranslate($t_x, $t_y, $returnstring = false) + { + // calculate elements of transformation matrix + $tm = []; + $tm[0] = 1; + $tm[1] = 0; + $tm[2] = 0; + $tm[3] = 1; + $tm[4] = $t_x * Mpdf::SCALE; + $tm[5] = -$t_y * Mpdf::SCALE; + + // translate the coordinate system + if ($returnstring) { + return($this->_transform($tm, true)); + } else { + $this->_transform($tm); + } + } + + function transformRotate($angle, $x = '', $y = '', $returnstring = false) + { + if ($x === '') { + $x = $this->x; + } + + if ($y === '') { + $y = $this->y; + } + + $angle = -$angle; + $y = ($this->h - $y) * Mpdf::SCALE; + $x *= Mpdf::SCALE; + + // calculate elements of transformation matrix + $tm = []; + $tm[0] = cos(deg2rad($angle)); + $tm[1] = sin(deg2rad($angle)); + $tm[2] = -$tm[1]; + $tm[3] = $tm[0]; + $tm[4] = $x + $tm[1] * $y - $tm[0] * $x; + $tm[5] = $y - $tm[0] * $y - $tm[1] * $x; + + // rotate the coordinate system around ($x,$y) + if ($returnstring) { + return $this->_transform($tm, true); + } else { + $this->_transform($tm); + } + } + + /** + * mPDF 5.7.3 TRANSFORMS + */ + function transformSkew($angle_x, $angle_y, $x = '', $y = '', $returnstring = false) + { + if ($x === '') { + $x = $this->x; + } + + if ($y === '') { + $y = $this->y; + } + + $angle_x = -$angle_x; + $angle_y = -$angle_y; + + $x *= Mpdf::SCALE; + $y = ($this->h - $y) * Mpdf::SCALE; + + // calculate elements of transformation matrix + $tm = []; + $tm[0] = 1; + $tm[1] = tan(deg2rad($angle_y)); + $tm[2] = tan(deg2rad($angle_x)); + $tm[3] = 1; + $tm[4] = -$tm[2] * $y; + $tm[5] = -$tm[1] * $x; + + // skew the coordinate system + if ($returnstring) { + return $this->_transform($tm, true); + } else { + $this->_transform($tm); + } + } + + function _transform($tm, $returnstring = false) + { + if ($returnstring) { + return(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); + } else { + $this->writer->write(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); + } + } + + // AUTOFONT ========================= + function markScriptToLang($html) + { + if ($this->onlyCoreFonts) { + return $html; + } + + $n = ''; + $a = preg_split('/<(.*?)>/ms', $html, -1, PREG_SPLIT_DELIM_CAPTURE); + foreach ($a as $i => $e) { + if ($i % 2 == 0) { + + // ignore if in Textarea + if ($i > 0 && strtolower(substr($a[$i - 1], 1, 8)) == 'textarea') { + $a[$i] = $e; + continue; + } + + $e = UtfString::strcode2utf($e); + $e = $this->lesser_entity_decode($e); + + $earr = $this->UTF8StringToArray($e, false); + + $scriptblock = 0; + $scriptblocks = []; + $scriptblocks[0] = 0; + $chardata = []; + $subchunk = 0; + $charctr = 0; + + foreach ($earr as $char) { + + $ucd_record = Ucdn::get_ucd_record($char); + $sbl = $ucd_record[6]; + + if ($sbl && $sbl != 40 && $sbl != 102) { + if ($scriptblock == 0) { + $scriptblock = $sbl; + $scriptblocks[$subchunk] = $scriptblock; + } elseif ($scriptblock > 0 && $scriptblock != $sbl) { + // NEW (non-common) Script encountered in this chunk. + // Start a new subchunk + $subchunk++; + $scriptblock = $sbl; + $charctr = 0; + $scriptblocks[$subchunk] = $scriptblock; + } + } + + $chardata[$subchunk][$charctr]['script'] = $sbl; + $chardata[$subchunk][$charctr]['uni'] = $char; + $charctr++; + } + + // If scriptblock[x] = common & non-baseScript + // and scriptblock[x+1] = baseScript + // Move common script from end of x to start of x+1 + for ($sch = 0; $sch < $subchunk; $sch++) { + if ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->baseScript && $scriptblocks[$sch + 1] == $this->baseScript) { + $end = count($chardata[$sch]) - 1; + while ($chardata[$sch][$end]['script'] == 0 && $end > 1) { // common script + $tmp = array_pop($chardata[$sch]); + array_unshift($chardata[$sch + 1], $tmp); + $end--; + } + } + } + + $o = ''; + for ($sch = 0; $sch <= $subchunk; $sch++) { + + if (isset($chardata[$sch])) { + $s = ''; + for ($j = 0; $j < count($chardata[$sch]); $j++) { + $s .= UtfString::code2utf($chardata[$sch][$j]['uni']); + } + + // ZZZ99 Undo lesser_entity_decode as above - but only for <>& + $s = str_replace("&", "&", $s); + $s = str_replace("<", "<", $s); + $s = str_replace(">", ">", $s); + + // Check Vietnamese if Latin script - even if Basescript + if ($scriptblocks[$sch] == Ucdn::SCRIPT_LATIN && $this->autoVietnamese && preg_match("/([" . $this->scriptToLanguage->getLanguageDelimiters('viet') . "])/u", $s)) { + $o .= '<span lang="vi" class="lang_vi">' . $s . '</span>'; + } elseif ($scriptblocks[$sch] == Ucdn::SCRIPT_ARABIC && $this->autoArabic) { // Check Arabic for different languages if Arabic script - even if Basescript + if (preg_match("/[" . $this->scriptToLanguage->getLanguageDelimiters('sindhi') . "]/u", $s)) { + $o .= '<span lang="sd" class="lang_sd">' . $s . '</span>'; + } elseif (preg_match("/[" . $this->scriptToLanguage->getLanguageDelimiters('urdu') . "]/u", $s)) { + $o .= '<span lang="ur" class="lang_ur">' . $s . '</span>'; + } elseif (preg_match("/[" . $this->scriptToLanguage->getLanguageDelimiters('pashto') . "]/u", $s)) { + $o .= '<span lang="ps" class="lang_ps">' . $s . '</span>'; + } elseif (preg_match("/[" . $this->scriptToLanguage->getLanguageDelimiters('persian') . "]/u", $s)) { + $o .= '<span lang="fa" class="lang_fa">' . $s . '</span>'; + } elseif ($this->baseScript != Ucdn::SCRIPT_ARABIC && $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch])) { + $o .= '<span lang="' . $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch]) . '" class="lang_' . $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch]) . '">' . $s . '</span>'; + } else { + // Just output chars + $o .= $s; + } + } elseif ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->baseScript && $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch])) { // Identify Script block if not Basescript, and mark up as language + // Encase in <span> + $o .= '<span lang="' . $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch]) . '" class="lang_' . $this->scriptToLanguage->getLanguageByScript($scriptblocks[$sch]) . '">'; + $o .= $s; + $o .= '</span>'; + } else { + // Just output chars + $o .= $s; + } + } + } + + $a[$i] = $o; + } else { + $a[$i] = '<' . $e . '>'; + } + } + + $n = implode('', $a); + + return $n; + } + + /* -- COLUMNS -- */ + /** + * Callback function from function printcolumnbuffer in mpdf + */ + function columnAdjustAdd($type, $k, $xadj, $yadj, $a, $b, $c = 0, $d = 0, $e = 0, $f = 0) + { + if ($type === 'Td') { // xpos,ypos + + $a += ($xadj * $k); + $b -= ($yadj * $k); + + return 'BT ' . sprintf('%.3F %.3F', $a, $b) . ' Td'; + + } elseif ($type === 're') { // xpos,ypos,width,height + + $a += ($xadj * $k); + $b -= ($yadj * $k); + + return sprintf('%.3F %.3F %.3F %.3F', $a, $b, $c, $d) . ' re'; + + } elseif ($type === 'l') { // xpos,ypos,x2pos,y2pos + + $a += ($xadj * $k); + $b -= ($yadj * $k); + + return sprintf('%.3F %.3F l', $a, $b); + + } elseif ($type === 'img') { // width,height,xpos,ypos + + $c += ($xadj * $k); + $d -= ($yadj * $k); + + return sprintf('q %.3F 0 0 %.3F %.3F %.3F', $a, $b, $c, $d) . ' cm /' . $e; + + } elseif ($type === 'draw') { // xpos,ypos + + $a += ($xadj * $k); + $b -= ($yadj * $k); + + return sprintf('%.3F %.3F m', $a, $b); + + } elseif ($type === 'bezier') { // xpos,ypos,x2pos,y2pos,x3pos,y3pos + + $a += ($xadj * $k); + $b -= ($yadj * $k); + $c += ($xadj * $k); + $d -= ($yadj * $k); + $e += ($xadj * $k); + $f -= ($yadj * $k); + + return sprintf('%.3F %.3F %.3F %.3F %.3F %.3F', $a, $b, $c, $d, $e, $f) . ' c'; + } + } + + /* -- END COLUMNS -- */ + + // mPDF 5.7.3 TRANSFORMS + function ConvertAngle($s, $makepositive = true) + { + if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i', $s, $m)) { + + $angle = $m[1] + 0; + + if (strtolower($m[2]) == 'deg') { + $angle = $angle; + } elseif (strtolower($m[2]) == 'grad') { + $angle *= (360 / 400); + } elseif (strtolower($m[2]) == 'rad') { + $angle = rad2deg($angle); + } + + while ($angle >= 360) { + $angle -= 360; + } + + while ($angle <= -360) { + $angle += 360; + } + + if ($makepositive) { // always returns an angle between 0 and 360deg + if ($angle < 0) { + $angle += 360; + } + } + + } else { + $angle = $s + 0; + } + + return $angle; + } + + function lesser_entity_decode($html) + { + // supports the most used entity codes (only does ascii safe characters) + $html = str_replace("<", "<", $html); + $html = str_replace(">", ">", $html); + + $html = str_replace("'", "'", $html); + $html = str_replace(""", '"', $html); + $html = str_replace("&", "&", $html); + + return $html; + } + + function AdjustHTML($html, $tabSpaces = 8) + { + $limit = ini_get('pcre.backtrack_limit'); + + if (0 >= (int) $limit) { + throw new \Mpdf\MpdfException(sprintf( + 'mPDF will not process HTML with disabled pcre.backtrack_limit to prevent unexpected behaviours, please set a positive backtrack limit.', + $limit + )); + } + + if (strlen($html) > (int) $limit) { + throw new \Mpdf\MpdfException(sprintf( + 'The HTML code size is larger than pcre.backtrack_limit %d. You should use WriteHTML() with smaller string lengths. Pass your HTML in smaller chunks.', + $limit + )); + } + + preg_match_all("/(<annotation.*?>)/si", $html, $m); + if (count($m[1])) { + for ($i = 0; $i < count($m[1]); $i++) { + $sub = preg_replace("/\n/si", Mpdf::OBJECT_IDENTIFIER, $m[1][$i]); + $html = preg_replace('/' . preg_quote($m[1][$i], '/') . '/si', $sub, $html); + } + } + + preg_match_all("/(<svg.*?<\/svg>)/si", $html, $svgi); + if (count($svgi[0])) { + for ($i = 0; $i < count($svgi[0]); $i++) { + $file = $this->cache->write('/_tempSVG' . uniqid(random_int(1, 100000), true) . '_' . $i . '.svg', $svgi[0][$i]); + $html = str_replace($svgi[0][$i], '<img src="' . $file . '" />', $html); + } + } + + // Remove javascript code from HTML (should not appear in the PDF file) + $html = preg_replace('/<script.*?<\/script>/is', '', $html); + + // Remove special comments + $html = preg_replace('/<!--mpdf/i', '', $html); + $html = preg_replace('/mpdf-->/i', '', $html); + + // Remove comments from HTML (should not appear in the PDF file) + $html = preg_replace('/<!--.*?-->/s', '', $html); + + $html = preg_replace('/\f/', '', $html); // replace formfeed by nothing + $html = preg_replace('/\r/', '', $html); // replace carriage return by nothing + + // Well formed XHTML end tags + $html = preg_replace('/<(br|hr)>/i', "<\\1 />", $html); // mPDF 6 + $html = preg_replace('/<(br|hr)\/>/i', "<\\1 />", $html); + + // Get rid of empty <thead></thead> etc + $html = preg_replace('/<tr>\s*<\/tr>/i', '', $html); + $html = preg_replace('/<thead>\s*<\/thead>/i', '', $html); + $html = preg_replace('/<tfoot>\s*<\/tfoot>/i', '', $html); + $html = preg_replace('/<table[^>]*>\s*<\/table>/i', '', $html); + + // Remove spaces at end of table cells + $html = preg_replace("/[ \n\r]+<\/t(d|h)/", '</t\\1', $html); + + $html = preg_replace("/[ ]*<dottab\s*[\/]*>[ ]*/", '<dottab />', $html); + + // Concatenates any Substitute characters from symbols/dingbats + $html = str_replace('</tts><tts>', '|', $html); + $html = str_replace('</ttz><ttz>', '|', $html); + $html = str_replace('</tta><tta>', '|', $html); + + $html = preg_replace('/<br \/>\s*/is', "<br />", $html); + + $html = preg_replace('/<wbr[ \/]*>\s*/is', "­", $html); + + // Preserve '\n's in content between the tags <pre> and </pre> + if (preg_match('/<pre/', $html)) { + + $html_a = preg_split('/(\<\/?pre[^\>]*\>)/', $html, -1, 2); + $h = []; + $c = 0; + + foreach ($html_a as $s) { + if ($c > 1 && preg_match('/^<\/pre/i', $s)) { + $c--; + $s = preg_replace('/<\/pre/i', '</innerpre', $s); + } elseif ($c > 0 && preg_match('/^<pre/i', $s)) { + $c++; + $s = preg_replace('/<pre/i', '<innerpre', $s); + } elseif (preg_match('/^<pre/i', $s)) { + $c++; + } elseif (preg_match('/^<\/pre/i', $s)) { + $c--; + } + array_push($h, $s); + } + + $html = implode('', $h); + } + + $thereispre = preg_match_all('#<pre(.*?)>(.*?)</pre>#si', $html, $temp); + + // Preserve '\n's in content between the tags <textarea> and </textarea> + $thereistextarea = preg_match_all('#<textarea(.*?)>(.*?)</textarea>#si', $html, $temp2); + $html = preg_replace('/[\n]/', ' ', $html); // replace linefeed by spaces + $html = preg_replace('/[\t]/', ' ', $html); // replace tabs by spaces + + // Converts < to < when not a tag + $html = preg_replace('/<([^!\/a-zA-Z_:])/i', '<\\1', $html); // mPDF 5.7.3 + $html = preg_replace("/[ ]+/", ' ', $html); + + $html = preg_replace('/\/li>\s+<\/(u|o)l/i', '/li></\\1l', $html); + $html = preg_replace('/\/(u|o)l>\s+<\/li/i', '/\\1l></li', $html); + $html = preg_replace('/\/li>\s+<\/(u|o)l/i', '/li></\\1l', $html); + $html = preg_replace('/\/li>\s+<li/i', '/li><li', $html); + $html = preg_replace('/<(u|o)l([^>]*)>[ ]+/i', '<\\1l\\2>', $html); + $html = preg_replace('/[ ]+<(u|o)l/i', '<\\1l', $html); + + // Make self closing tabs valid XHTML + // Tags which are self-closing: 1) Replaceable and 2) Non-replaced items + $selftabs = 'input|hr|img|br|barcode|dottab'; + $selftabs2 = 'indexentry|indexinsert|bookmark|watermarktext|watermarkimage|column_break|columnbreak|newcolumn|newpage|page_break|pagebreak|formfeed|columns|toc|tocpagebreak|setpageheader|setpagefooter|sethtmlpageheader|sethtmlpagefooter|annotation'; + + // Fix self-closing tags which don't close themselves + $html = preg_replace('/(<(' . $selftabs . '|' . $selftabs2 . ')[^>\/]*)>/i', '\\1 />', $html); + + // Fix self-closing tags that don't include a space between the tag name and the closing slash + $html = preg_replace('/(<(' . $selftabs . '|' . $selftabs2 . '))\/>/i', '\\1 />', $html); + + $iterator = 0; + while ($thereispre) { // Recover <pre attributes>content</pre> + $temp[2][$iterator] = preg_replace('/<([^!\/a-zA-Z_:])/', '<\\1', $temp[2][$iterator]); // mPDF 5.7.2 // mPDF 5.7.3 + + $temp[2][$iterator] = preg_replace_callback("/^([^\n\t]*?)\t/m", [$this, 'tabs2spaces_callback'], $temp[2][$iterator]); // mPDF 5.7+ + $temp[2][$iterator] = preg_replace('/\t/', str_repeat(" ", $tabSpaces), $temp[2][$iterator]); + + $temp[2][$iterator] = preg_replace('/\n/', "<br />", $temp[2][$iterator]); + $temp[2][$iterator] = str_replace('\\', "\\\\", $temp[2][$iterator]); + // $html = preg_replace('#<pre(.*?)>(.*?)</pre>#si','<erp'.$temp[1][$iterator].'>'.$temp[2][$iterator].'</erp>',$html,1); + $html = preg_replace('#<pre(.*?)>(.*?)</pre>#si', '<erp' . $temp[1][$iterator] . '>' . str_replace('$', '\$', $temp[2][$iterator]) . '</erp>', $html, 1); // mPDF 5.7+ + $thereispre--; + $iterator++; + } + + $iterator = 0; + while ($thereistextarea) { // Recover <textarea attributes>content</textarea> + $temp2[2][$iterator] = preg_replace('/\t/', str_repeat(" ", $tabSpaces), $temp2[2][$iterator]); + $temp2[2][$iterator] = str_replace('\\', "\\\\", $temp2[2][$iterator]); + $html = preg_replace('#<textarea(.*?)>(.*?)</textarea>#si', '<aeratxet' . $temp2[1][$iterator] . '>' . trim($temp2[2][$iterator]) . '</aeratxet>', $html, 1); + $thereistextarea--; + $iterator++; + } + + // Restore original tag names + $html = str_replace("<erp", "<pre", $html); + $html = str_replace("</erp>", "</pre>", $html); + $html = str_replace("<aeratxet", "<textarea", $html); + $html = str_replace("</aeratxet>", "</textarea>", $html); + $html = str_replace("</innerpre", "</pre", $html); + $html = str_replace("<innerpre", "<pre", $html); + + $html = preg_replace('/<textarea([^>]*)><\/textarea>/si', '<textarea\\1> </textarea>', $html); + $html = preg_replace('/(<table[^>]*>)\s*(<caption)(.*?<\/caption>)(.*?<\/table>)/si', '\\2 position="top"\\3\\1\\4\\2 position="bottom"\\3', $html); // *TABLES* + + if ($this->use_kwt) { + $returnHtml = preg_replace('/<(h[1-6])([^>]*(?<!\/))(>[^>]*<\/\\1>\s*<table)/si', '<\\1\\2 keep-with-table="1"\\3', $html); + /* If no errors then save the return value */ + if (preg_last_error() === PREG_NO_ERROR) { + $html = $returnHtml; + } + } + + $html = preg_replace('/' . Mpdf::OBJECT_IDENTIFIER . '/', "\n", $html); + + // Fixes <p>₹</p> which browser copes with even though it is wrong! + $html = preg_replace("/(&#[x]{0,1}[0-9a-f]{1,5})</i", "\\1;<", $html); + + return $html; + } + + // mPDF 5.7+ + function tabs2spaces_callback($matches) + { + return (stripslashes($matches[1]) . str_repeat(' ', $this->tabSpaces - (mb_strlen(stripslashes($matches[1])) % $this->tabSpaces))); + } + + // mPDF 5.7+ + function date_callback($matches) + { + return date($matches[1]); + } + + // ========== OVERWRITE SEARCH STRING IN A PDF FILE ================ + function OverWrite($file_in, $search, $replacement, $dest = Destination::DOWNLOAD, $file_out = "mpdf") + { + $pdf = file_get_contents($file_in); + + if (!is_array($search)) { + $x = $search; + $search = [$x]; + } + if (!is_array($replacement)) { + $x = $replacement; + $replacement = [$x]; // mPDF 5.7.4 + } + + if (!$this->onlyCoreFonts && !$this->usingCoreFont) { + foreach ($search as $k => $val) { + $search[$k] = $this->writer->utf8ToUtf16BigEndian($search[$k], false); + $search[$k] = $this->writer->escape($search[$k]); + $replacement[$k] = $this->writer->utf8ToUtf16BigEndian($replacement[$k], false); + $replacement[$k] = $this->writer->escape($replacement[$k]); + } + } else { + foreach ($replacement as $k => $val) { + $replacement[$k] = mb_convert_encoding($replacement[$k], $this->mb_enc, 'utf-8'); + $replacement[$k] = $this->writer->escape($replacement[$k]); + } + } + + // Get xref into array + $xref = []; + preg_match("/xref\n0 (\d+)\n(.*?)\ntrailer/s", $pdf, $m); + $xref_objid = $m[1]; + preg_match_all('/(\d{10}) (\d{5}) (f|n)/', $m[2], $x); + for ($i = 0; $i < count($x[0]); $i++) { + $xref[] = [(int) $x[1][$i], $x[2][$i], $x[3][$i]]; + } + + $changes = []; + preg_match("/<<\s*\/Type\s*\/Pages\s*\/Kids\s*\[(.*?)\]\s*\/Count/s", $pdf, $m); + preg_match_all("/(\d+) 0 R /s", $m[1], $o); + $objlist = $o[1]; + + foreach ($objlist as $obj) { + if ($this->compress) { + preg_match("/" . ($obj + 1) . " 0 obj\n<<\s*\/Filter\s*\/FlateDecode\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s", $pdf, $m); + } else { + preg_match("/" . ($obj + 1) . " 0 obj\n<<\s*\/Length (\d+)>>\nstream\n(.*?)\nendstream\n/s", $pdf, $m); + } + + $s = $m[2]; + if (!$s) { + continue; + } + + $oldlen = $m[1]; + + if ($this->encrypted) { + $s = $this->protection->rc4($this->protection->objectKey($obj + 1), $s); + } + + if ($this->compress) { + $s = gzuncompress($s); + } + + foreach ($search as $k => $val) { + $s = str_replace($search[$k], $replacement[$k], $s); + } + + if ($this->compress) { + $s = gzcompress($s); + } + + if ($this->encrypted) { + $s = $this->protection->rc4($this->protection->objectKey($obj + 1), $s); + } + + $newlen = strlen($s); + + $changes[($xref[$obj + 1][0])] = ($newlen - $oldlen) + (strlen($newlen) - strlen($oldlen)); + + if ($this->compress) { + $newstr = ($obj + 1) . " 0 obj\n<</Filter /FlateDecode /Length " . $newlen . ">>\nstream\n" . $s . "\nendstream\n"; + } else { + $newstr = ($obj + 1) . " 0 obj\n<</Length " . $newlen . ">>\nstream\n" . $s . "\nendstream\n"; + } + + $pdf = str_replace($m[0], $newstr, $pdf); + } + + // Update xref in PDF + krsort($changes); + $newxref = "xref\n0 " . $xref_objid . "\n"; + foreach ($xref as $v) { + foreach ($changes as $ck => $cv) { + if ($v[0] > $ck) { + $v[0] += $cv; + } + } + $newxref .= sprintf('%010d', $v[0]) . ' ' . $v[1] . ' ' . $v[2] . " \n"; + } + $newxref .= "trailer"; + $pdf = preg_replace("/xref\n0 \d+\n.*?\ntrailer/s", $newxref, $pdf); + + // Update startxref in PDF + preg_match("/startxref\n(\d+)\n%%EOF/s", $pdf, $m); + $startxref = $m[1]; + $startxref += array_sum($changes); + $pdf = preg_replace("/startxref\n(\d+)\n%%EOF/s", "startxref\n" . $startxref . "\n%%EOF", $pdf); + + // OUTPUT + switch ($dest) { + case Destination::INLINE: + if (isset($_SERVER['SERVER_NAME'])) { + // We send to a browser + header('Content-Type: application/pdf'); + header('Content-Length: ' . strlen($pdf)); + header('Content-disposition: inline; filename=' . $file_out); + } + + echo $pdf; + + break; + + case Destination::FILE: + if (!$file_out) { + $file_out = 'mpdf.pdf'; + } + + $f = fopen($file_out, 'wb'); + + if (!$f) { + throw new \Mpdf\MpdfException('Unable to create output file: ' . $file_out); + } + + fwrite($f, $pdf, strlen($pdf)); + + fclose($f); + + break; + + case Destination::STRING_RETURN: + return $pdf; + + case Destination::DOWNLOAD: // Download file + default: + if (isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { + header('Content-Type: application/force-download'); + } else { + header('Content-Type: application/octet-stream'); + } + + header('Content-Length: ' . strlen($pdf)); + header('Content-disposition: attachment; filename=' . $file_out); + + echo $pdf; + + break; + } + } + + + function Thumbnail($file, $npr = 3, $spacing = 10) + { + // $npr = number per row + $w = (($this->pgwidth + $spacing) / $npr) - $spacing; + $oldlinewidth = $this->LineWidth; + $this->SetLineWidth(0.02); + $this->SetDColor($this->colorConverter->convert(0, $this->PDFAXwarnings)); + $h = 0; + $maxh = 0; + $x = $_x = $this->lMargin; + $_y = $this->tMargin; + + if ($this->y == 0) { + $y = $_y; + } else { + $y = $this->y; + } + + $pagecount = $this->setSourceFile($file); + + for ($n = 1; $n <= $pagecount; $n++) { + $tplidx = $this->importPage($n); + $size = $this->useTemplate($tplidx, $x, $y, $w); + $this->Rect($x, $y, $size['width'], $size['height']); + $h = max($h, $size['height']); + $maxh = max($h, $maxh); + + if ($n % $npr == 0) { + if (($y + $h + $spacing + $maxh) > $this->PageBreakTrigger && $n != $pagecount) { + $this->AddPage(); + $x = $_x; + $y = $_y; + } else { + $y += $h + $spacing; + $x = $_x; + $h = 0; + } + } else { + $x += $w + $spacing; + } + } + $this->SetLineWidth($oldlinewidth); + } + + function SetPageTemplate($tplidx = '') + { + if (!isset($this->importedPages[$tplidx])) { + $this->pageTemplate = ''; + return false; + } + $this->pageTemplate = $tplidx; + } + + function SetDocTemplate($file = '', $continue = 0, $continue2pages = 0) + { + $this->docTemplate = $file; + $this->docTemplateContinue = $continue; + $this->docTemplateContinue2pages = $continue2pages; + + if ($this->docTemplateContinue2pages) { // Enable continue when continue2pages is set + $this->docTemplateContinue = $this->docTemplateContinue2pages; + } + } + + /* -- END IMPORTS -- */ + + // JAVASCRIPT + function _set_object_javascript($string) + { + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/S /JavaScript '); + $this->writer->write('/JS ' . $this->writer->string($string)); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + + function SetJS($script) + { + $this->js = $script; + } + + /** + * This function takes the last comma or dot (if any) to make a clean float, ignoring thousand separator, currency or any other letter + * + * @param string $num + * @see http://php.net/manual/de/function.floatval.php#114486 + * @return float + */ + public function toFloat($num) + { + $dotPos = strrpos($num, '.'); + $commaPos = strrpos($num, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) { + return floatval(preg_replace('/[^0-9]/', '', $num)); + } + + return floatval( + preg_replace('/[^0-9]/', '', substr($num, 0, $sep)) . '.' . + preg_replace('/[^0-9]/', '', substr($num, $sep+1, strlen($num))) + ); + } + + public function getFontDescriptor() + { + return $this->fontDescriptor; + } + + /** + * Temporarily return the method to preserve example 44 yearbook + */ + public function _out($s) + { + $this->writer->write($s); + } + + /** + * @param string $html + * @param string $PAGENO + * @param string $NbPgGp + * @param string $NbPg + * @return string + */ + protected function aliasReplace($html, $PAGENO, $NbPgGp, $NbPg) + { + // Replaces for header and footer + $html = str_replace('{PAGENO}', $PAGENO, $html); + $html = str_replace($this->aliasNbPgGp, $NbPgGp, $html); // {nbpg} + $html = str_replace($this->aliasNbPg, $NbPg, $html); // {nb} + + // Replaces for the body + $html = str_replace(mb_convert_encoding('{PAGENO}', 'UTF-16BE', 'UTF-8'), mb_convert_encoding($PAGENO, 'UTF-16BE', 'UTF-8'), $html); + $html = str_replace(mb_convert_encoding($this->aliasNbPgGp, 'UTF-16BE', 'UTF-8'), mb_convert_encoding($NbPgGp, 'UTF-16BE', 'UTF-8'), $html); // {nbpg} + $html = str_replace(mb_convert_encoding($this->aliasNbPg, 'UTF-16BE', 'UTF-8'), mb_convert_encoding($NbPg, 'UTF-16BE', 'UTF-8'), $html); // {nb} + + // Date replace + $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7 + + return $html; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/MpdfException.php b/src/vendor/mpdf/mpdf/src/MpdfException.php new file mode 100644 index 000000000..f84535490 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/MpdfException.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf; + +class MpdfException extends \ErrorException +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/MpdfImageException.php b/src/vendor/mpdf/mpdf/src/MpdfImageException.php new file mode 100644 index 000000000..c8f4ca094 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/MpdfImageException.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf; + +class MpdfImageException extends \Mpdf\MpdfException +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/Otl.php b/src/vendor/mpdf/mpdf/src/Otl.php new file mode 100644 index 000000000..a89fd92ab --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Otl.php @@ -0,0 +1,6242 @@ +<?php + +namespace Mpdf; + +use Mpdf\Strict; + +use Mpdf\Css\TextVars; +use Mpdf\Fonts\FontCache; + +use Mpdf\Shaper\Indic; +use Mpdf\Shaper\Myanmar; +use Mpdf\Shaper\Sea; + +use Mpdf\Utils\UtfString; + +class Otl +{ + + use Strict; + + const _OTL_OLD_SPEC_COMPAT_1 = true; + const _DICT_NODE_TYPE_SPLIT = 0x01; + const _DICT_NODE_TYPE_LINEAR = 0x02; + const _DICT_INTERMEDIATE_MATCH = 0x03; + const _DICT_FINAL_MATCH = 0x04; + + private $mpdf; + + private $fontCache; + + var $arabLeftJoining; + + var $arabRightJoining; + + var $arabTransparentJoin; + + var $arabTransparent; + + var $GSUBdata; + + var $GPOSdata; + + var $GSUBfont; + + var $fontkey; + + var $ttfOTLdata; + + var $glyphIDtoUni; + + var $_pos; + + var $GSUB_offset; + + var $GPOS_offset; + + var $MarkAttachmentType; + + var $MarkGlyphSets; + + var $GlyphClassMarks; + + var $GlyphClassLigatures; + + var $GlyphClassBases; + + var $GlyphClassComponents; + + var $Ignores; + + var $LuCoverage; + + var $OTLdata; + + var $assocLigs; + + var $assocMarks; + + var $shaper; + + var $restrictToSyllable; + + var $lbdicts; // Line-breaking dictionaries + + var $LuDataCache; + + var $arabGlyphs; + + var $current_fh; + + var $Entry; + + var $Exit; + + var $GDEFdata; + + var $GPOSLookups; + + var $GSLuCoverage; + + var $GSUB_length; + + var $GSUBLookups; + + var $schOTLdata; + + var $lastBidiStrongType; + + var $debugOTL = false; + + public function __construct(Mpdf $mpdf, FontCache $fontCache) + { + $this->mpdf = $mpdf; + $this->fontCache = $fontCache; + + $this->current_fh = ''; + + $this->lbdicts = []; + $this->LuDataCache = []; + } + + function applyOTL($str, $useOTL) + { + if (!$this->arabLeftJoining) { + $this->arabic_initialise(); + } + + $this->OTLdata = []; + if (trim($str) == '') { + return $str; + } + if (!$useOTL) { + return $str; + } + + // 1. Load GDEF data + //============================== + $this->fontkey = $this->mpdf->CurrentFont['fontkey']; + $this->glyphIDtoUni = $this->mpdf->CurrentFont['glyphIDtoUni']; + $fontCacheFilename = $this->fontkey . '.GDEFdata.json'; + if (!isset($this->GDEFdata[$this->fontkey]) && $this->fontCache->jsonHas($fontCacheFilename)) { + $font = $this->fontCache->jsonLoad($fontCacheFilename); + + $this->GSUB_offset = $this->GDEFdata[$this->fontkey]['GSUB_offset'] = $font['GSUB_offset']; + $this->GPOS_offset = $this->GDEFdata[$this->fontkey]['GPOS_offset'] = $font['GPOS_offset']; + $this->GSUB_length = $this->GDEFdata[$this->fontkey]['GSUB_length'] = $font['GSUB_length']; + $this->MarkAttachmentType = $this->GDEFdata[$this->fontkey]['MarkAttachmentType'] = $font['MarkAttachmentType']; + $this->MarkGlyphSets = $this->GDEFdata[$this->fontkey]['MarkGlyphSets'] = $font['MarkGlyphSets']; + $this->GlyphClassMarks = $this->GDEFdata[$this->fontkey]['GlyphClassMarks'] = $font['GlyphClassMarks']; + $this->GlyphClassLigatures = $this->GDEFdata[$this->fontkey]['GlyphClassLigatures'] = $font['GlyphClassLigatures']; + $this->GlyphClassComponents = $this->GDEFdata[$this->fontkey]['GlyphClassComponents'] = $font['GlyphClassComponents']; + $this->GlyphClassBases = $this->GDEFdata[$this->fontkey]['GlyphClassBases'] = $font['GlyphClassBases']; + } else { + $this->GSUB_offset = $this->GDEFdata[$this->fontkey]['GSUB_offset']; + $this->GPOS_offset = $this->GDEFdata[$this->fontkey]['GPOS_offset']; + $this->GSUB_length = $this->GDEFdata[$this->fontkey]['GSUB_length']; + $this->MarkAttachmentType = $this->GDEFdata[$this->fontkey]['MarkAttachmentType']; + $this->MarkGlyphSets = $this->GDEFdata[$this->fontkey]['MarkGlyphSets']; + $this->GlyphClassMarks = $this->GDEFdata[$this->fontkey]['GlyphClassMarks']; + $this->GlyphClassLigatures = $this->GDEFdata[$this->fontkey]['GlyphClassLigatures']; + $this->GlyphClassComponents = $this->GDEFdata[$this->fontkey]['GlyphClassComponents']; + $this->GlyphClassBases = $this->GDEFdata[$this->fontkey]['GlyphClassBases']; + } + + // 2. Prepare string as HEX string and Analyse character properties + //================================================================= + $earr = $this->mpdf->UTF8StringToArray($str, false); + + $scriptblock = 0; + $scriptblocks = []; + $scriptblocks[0] = 0; + $vstr = ''; + $OTLdata = []; + $subchunk = 0; + $charctr = 0; + foreach ($earr as $char) { + $ucd_record = Ucdn::get_ucd_record($char); + $sbl = $ucd_record[6]; + + // Special case - Arabic End of Ayah + if ($char == 1757) { + $sbl = Ucdn::SCRIPT_ARABIC; + } + + if ($sbl && $sbl != 40 && $sbl != 102) { + if ($scriptblock == 0) { + $scriptblock = $sbl; + $scriptblocks[$subchunk] = $scriptblock; + } elseif ($scriptblock > 0 && $scriptblock != $sbl) { + // ************************************************* + // NEW (non-common) Script encountered in this chunk. Start a new subchunk + $subchunk++; + $scriptblock = $sbl; + $charctr = 0; + $scriptblocks[$subchunk] = $scriptblock; + } + } + + $OTLdata[$subchunk][$charctr]['general_category'] = $ucd_record[0]; + $OTLdata[$subchunk][$charctr]['bidi_type'] = $ucd_record[2]; + + //$OTLdata[$subchunk][$charctr]['combining_class'] = $ucd_record[1]; + //$OTLdata[$subchunk][$charctr]['bidi_type'] = $ucd_record[2]; + //$OTLdata[$subchunk][$charctr]['mirrored'] = $ucd_record[3]; + //$OTLdata[$subchunk][$charctr]['east_asian_width'] = $ucd_record[4]; + //$OTLdata[$subchunk][$charctr]['normalization_check'] = $ucd_record[5]; + //$OTLdata[$subchunk][$charctr]['script'] = $ucd_record[6]; + + $charasstr = $this->unicode_hex($char); + + if (strpos($this->GlyphClassMarks, $charasstr) !== false) { + $OTLdata[$subchunk][$charctr]['group'] = 'M'; + } elseif ($char == 32 || $char == 12288) { + $OTLdata[$subchunk][$charctr]['group'] = 'S'; + } // 12288 = 0x3000 = CJK space + else { + $OTLdata[$subchunk][$charctr]['group'] = 'C'; + } + + $OTLdata[$subchunk][$charctr]['uni'] = $char; + $OTLdata[$subchunk][$charctr]['hex'] = $charasstr; + $charctr++; + } + + /* PROCESS EACH SUBCHUNK WITH DIFFERENT SCRIPTS */ + for ($sch = 0; $sch <= $subchunk; $sch++) { + $this->OTLdata = $OTLdata[$sch]; + $scriptblock = $scriptblocks[$sch]; + + // 3. Get Appropriate Scripts, and Shaper engine from analysing text and list of available scripts/langsys in font + //============================== + // Based on actual script block of text, select shaper (and line-breaking dictionaries) + if (Ucdn::SCRIPT_DEVANAGARI <= $scriptblock && $scriptblock <= Ucdn::SCRIPT_MALAYALAM) { + $this->shaper = "I"; + } // INDIC shaper + elseif ($scriptblock == Ucdn::SCRIPT_ARABIC || $scriptblock == Ucdn::SCRIPT_SYRIAC) { + $this->shaper = "A"; + } // ARABIC shaper + elseif ($scriptblock == Ucdn::SCRIPT_NKO || $scriptblock == Ucdn::SCRIPT_MANDAIC) { + $this->shaper = "A"; + } // ARABIC shaper + elseif ($scriptblock == Ucdn::SCRIPT_KHMER) { + $this->shaper = "K"; + } // KHMER shaper + elseif ($scriptblock == Ucdn::SCRIPT_THAI) { + $this->shaper = "T"; + } // THAI shaper + elseif ($scriptblock == Ucdn::SCRIPT_LAO) { + $this->shaper = "L"; + } // LAO shaper + elseif ($scriptblock == Ucdn::SCRIPT_SINHALA) { + $this->shaper = "S"; + } // SINHALA shaper + elseif ($scriptblock == Ucdn::SCRIPT_MYANMAR) { + $this->shaper = "M"; + } // MYANMAR shaper + elseif ($scriptblock == Ucdn::SCRIPT_NEW_TAI_LUE) { + $this->shaper = "E"; + } // SEA South East Asian shaper + elseif ($scriptblock == Ucdn::SCRIPT_CHAM) { + $this->shaper = "E"; + } // SEA South East Asian shaper + elseif ($scriptblock == Ucdn::SCRIPT_TAI_THAM) { + $this->shaper = "E"; + } // SEA South East Asian shaper + else { + $this->shaper = ""; + } + // Get scripttag based on actual text script + $scripttag = Ucdn::$uni_scriptblock[$scriptblock]; + + $GSUBscriptTag = ''; + $GSUBlangsys = ''; + $GPOSscriptTag = ''; + $GPOSlangsys = ''; + $is_old_spec = false; + + $ScriptLang = $this->mpdf->CurrentFont['GSUBScriptLang']; + if (count($ScriptLang)) { + list($GSUBscriptTag, $is_old_spec) = $this->_getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $this->shaper, $useOTL, 'GSUB'); + if ($this->mpdf->fontLanguageOverride && strpos($ScriptLang[$GSUBscriptTag], $this->mpdf->fontLanguageOverride) !== false) { + $GSUBlangsys = str_pad($this->mpdf->fontLanguageOverride, 4); + } elseif ($GSUBscriptTag && isset($ScriptLang[$GSUBscriptTag]) && $ScriptLang[$GSUBscriptTag] != '') { + $GSUBlangsys = $this->_getOTLLangTag($this->mpdf->currentLang, $ScriptLang[$GSUBscriptTag]); + } + } + $ScriptLang = $this->mpdf->CurrentFont['GPOSScriptLang']; + + // NB If after GSUB, the same script/lang exist for GPOS, just use these... + if ($GSUBscriptTag && $GSUBlangsys && isset($ScriptLang[$GSUBscriptTag]) && strpos($ScriptLang[$GSUBscriptTag], $GSUBlangsys) !== false) { + $GPOSlangsys = $GSUBlangsys; + $GPOSscriptTag = $GSUBscriptTag; + } // else repeat for GPOS + // [Font XBRiyaz has GSUB tables for latn, but not GPOS for latn] + elseif (count($ScriptLang)) { + list($GPOSscriptTag, $dummy) = $this->_getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $this->shaper, $useOTL, 'GPOS'); + if ($GPOSscriptTag && $this->mpdf->fontLanguageOverride && strpos($ScriptLang[$GPOSscriptTag], $this->mpdf->fontLanguageOverride) !== false) { + $GPOSlangsys = str_pad($this->mpdf->fontLanguageOverride, 4); + } elseif ($GPOSscriptTag && isset($ScriptLang[$GPOSscriptTag]) && $ScriptLang[$GPOSscriptTag] != '') { + $GPOSlangsys = $this->_getOTLLangTag($this->mpdf->currentLang, $ScriptLang[$GPOSscriptTag]); + } + } + + // This is just for the font_dump_OTL utility to set script and langsys override + // $mpdf->overrideOTLsettings does not exist, this is never called + /*if (isset($this->mpdf->overrideOTLsettings) && isset($this->mpdf->overrideOTLsettings[$this->fontkey])) { + $GSUBscriptTag = $GPOSscriptTag = $this->mpdf->overrideOTLsettings[$this->fontkey]['script']; + $GSUBlangsys = $GPOSlangsys = $this->mpdf->overrideOTLsettings[$this->fontkey]['lang']; + }*/ + + if (!$GSUBscriptTag && !$GSUBlangsys && !$GPOSscriptTag && !$GPOSlangsys) { + // Remove ZWJ and ZWNJ + for ($i = 0; $i < count($this->OTLdata); $i++) { + if ($this->OTLdata[$i]['uni'] == 8204 || $this->OTLdata[$i]['uni'] == 8205) { + array_splice($this->OTLdata, $i, 1); + } + } + $this->schOTLdata[$sch] = $this->OTLdata; + $this->OTLdata = []; + continue; + } + + // Don't use MYANMAR shaper unless using v2 scripttag + if ($this->shaper == 'M' && $GSUBscriptTag != 'mym2') { + $this->shaper = ''; + } + + $GSUBFeatures = (isset($this->mpdf->CurrentFont['GSUBFeatures'][$GSUBscriptTag][$GSUBlangsys]) ? $this->mpdf->CurrentFont['GSUBFeatures'][$GSUBscriptTag][$GSUBlangsys] : false); + $GPOSFeatures = (isset($this->mpdf->CurrentFont['GPOSFeatures'][$GPOSscriptTag][$GPOSlangsys]) ? $this->mpdf->CurrentFont['GPOSFeatures'][$GPOSscriptTag][$GPOSlangsys] : false); + + $this->assocLigs = []; // Ligatures[$posarr lpos] => nc + $this->assocMarks = []; // assocMarks[$posarr mpos] => array(compID, ligPos) + + if (!isset($this->GDEFdata[$this->fontkey]['GSUBGPOStables'])) { + $this->ttfOTLdata = $this->GDEFdata[$this->fontkey]['GSUBGPOStables'] = $this->fontCache->load($this->fontkey . '.GSUBGPOStables.dat', 'rb'); + if (!$this->ttfOTLdata) { + throw new \Mpdf\MpdfException('Can\'t open file ' . $this->fontCache->tempFilename($this->fontkey . '.GSUBGPOStables.dat')); + } + } else { + $this->ttfOTLdata = $this->GDEFdata[$this->fontkey]['GSUBGPOStables']; + } + + if ($this->debugOTL) { + $this->_dumpproc('BEGIN', '-', '-', '-', '-', -1, '-', 0); + } + + //////////////////////////////////////////////////////////////// + ///////// LINE BREAKING FOR KHMER, THAI + LAO ///////////////// + //////////////////////////////////////////////////////////////// + // Insert U+200B at word boundaries using dictionaries + if ($this->mpdf->useDictionaryLBR && ($this->shaper == "K" || $this->shaper == "T" || $this->shaper == "L")) { + // Sets $this->OTLdata[$i]['wordend']=true at possible end of word boundaries + $this->seaLineBreaking(); + } // Insert U+200B at word boundaries for Tibetan + elseif ($this->mpdf->useTibetanLBR && $scriptblock == Ucdn::SCRIPT_TIBETAN) { + // Sets $this->OTLdata[$i]['wordend']=true at possible end of word boundaries + $this->tibetanLineBreaking(); + } + + + //////////////////////////////////////////////////////////////// + ////////// GSUB ///////////////////////////////// + //////////////////////////////////////////////////////////////// + if (($useOTL & 0xFF) && $GSUBscriptTag && $GSUBlangsys && $GSUBFeatures) { + // 4. Load GSUB data, Coverage & Lookups + //================================================================= + + $this->GSUBfont = $this->fontkey . '.GSUB.' . $GSUBscriptTag . '.' . $GSUBlangsys; + + if (!isset($this->GSUBdata[$this->GSUBfont])) { + $fontCacheFilename = $this->GSUBfont . '.json'; + if ($this->fontCache->jsonHas($fontCacheFilename)) { + $font = $this->fontCache->jsonLoad($fontCacheFilename); + + $this->GSUBdata[$this->GSUBfont]['rtlSUB'] = $font['rtlSUB']; + $this->GSUBdata[$this->GSUBfont]['finals'] = $font['finals']; + if ($this->shaper == 'I') { + $this->GSUBdata[$this->GSUBfont]['rphf'] = $font['rphf']; + $this->GSUBdata[$this->GSUBfont]['half'] = $font['half']; + $this->GSUBdata[$this->GSUBfont]['pref'] = $font['pref']; + $this->GSUBdata[$this->GSUBfont]['blwf'] = $font['blwf']; + $this->GSUBdata[$this->GSUBfont]['pstf'] = $font['pstf']; + } + } else { + $this->GSUBdata[$this->GSUBfont] = ['rtlSUB' => [], 'rphf' => [], 'rphf' => [], + 'pref' => [], 'blwf' => [], 'pstf' => [], 'finals' => '' + ]; + } + } + + $fontCacheFilename = $this->fontkey . '.GSUBdata.json'; + if (!isset($this->GSUBdata[$this->fontkey]) && $this->fontCache->jsonHas($fontCacheFilename)) { + $this->GSLuCoverage = $this->GSUBdata[$this->fontkey]['GSLuCoverage'] = $this->fontCache->jsonLoad($fontCacheFilename); + } else { + $this->GSLuCoverage = $this->GSUBdata[$this->fontkey]['GSLuCoverage']; + } + + $this->GSUBLookups = $this->mpdf->CurrentFont['GSUBLookups']; + + + // 5(A). GSUB - Shaper - ARABIC + //============================== + if ($this->shaper == 'A') { + //----------------------------------------------------------------------------------- + // a. Apply initial GSUB Lookups (in order specified in lookup list but only selecting from certain tags) + //----------------------------------------------------------------------------------- + $tags = 'locl ccmp'; + $omittags = ''; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, true); + } + $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys); + + //----------------------------------------------------------------------------------- + // b. Apply context-specific forms GSUB Lookups (initial, isolated, medial, final) + //----------------------------------------------------------------------------------- + // Arab and Syriac are the only scripts requiring the special joining - which takes the place of + // isol fina medi init rules in GSUB (+ fin2 fin3 med2 in Syriac syrc) + $tags = 'isol fina fin2 fin3 medi med2 init'; + $omittags = ''; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, true); + } + + $this->arabGlyphs = $this->GSUBdata[$this->GSUBfont]['rtlSUB']; + + $gcms = explode("| ", $this->GlyphClassMarks); + $gcm = []; + foreach ($gcms as $g) { + $gcm[hexdec($g)] = 1; + } + $this->arabTransparentJoin = $this->arabTransparent + $gcm; + $this->arabic_shaper($usetags, $GSUBscriptTag); + + //----------------------------------------------------------------------------------- + // c. Set Kashida points (after joining occurred - medi, fina, init) but before other substitutions + //----------------------------------------------------------------------------------- + //if ($scriptblock == Ucdn::SCRIPT_ARABIC ) { + for ($i = 0; $i < count($this->OTLdata); $i++) { + // Put the kashida marker on the character BEFORE which is inserted the kashida + // Kashida marker is inverse of priority i.e. Priority 1 => 7, Priority 7 => 1. + // Priority 1 User-inserted Kashida 0640 = Tatweel + // The user entered a Kashida in a position + // Position: Before the user-inserted kashida + if ($this->OTLdata[$i]['uni'] == 0x0640) { + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 8; // Put before the next character + } // Priority 2 Seen (0633) FEB3, FEB4; Sad (0635) FEBB, FEBC + // Initial or medial form + // Connecting to the next character + // Position: After the character + elseif ($this->OTLdata[$i]['uni'] == 0xFEB3 || $this->OTLdata[$i]['uni'] == 0xFEB4 || $this->OTLdata[$i]['uni'] == 0xFEBB || $this->OTLdata[$i]['uni'] == 0xFEBC) { + $checkpos = $i + 1; + while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + if (isset($this->OTLdata[$checkpos])) { + $this->OTLdata[$checkpos]['GPOSinfo']['kashida'] = 7; // Put after marks on next character + } + } // Priority 3 Taa Marbutah (0629) FE94; Haa (062D) FEA2; Dal (062F) FEAA + // Final form + // Connecting to previous character + // Position: Before the character + elseif ($this->OTLdata[$i]['uni'] == 0xFE94 || $this->OTLdata[$i]['uni'] == 0xFEA2 || $this->OTLdata[$i]['uni'] == 0xFEAA) { + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 6; + } // Priority 4 Alef (0627) FE8E; Tah (0637) FEC2; Lam (0644) FEDE; Kaf (0643) FEDA; Gaf (06AF) FB93 + // Final form + // Connecting to previous character + // Position: Before the character + elseif ($this->OTLdata[$i]['uni'] == 0xFE8E || $this->OTLdata[$i]['uni'] == 0xFEC2 || $this->OTLdata[$i]['uni'] == 0xFEDE || $this->OTLdata[$i]['uni'] == 0xFEDA || $this->OTLdata[$i]['uni'] == 0xFB93) { + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 5; + } // Priority 5 RA (0631) FEAE; Ya (064A) FEF2 FEF4; Alef Maqsurah (0649) FEF0 FBE9 + // Final or Medial form + // Connected to preceding medial BAA (0628) = FE92 + // Position: Before preceding medial Baa + // Although not mentioned in spec, added Farsi Yeh (06CC) FBFD FBFF; equivalent to 064A or 0649 + elseif ($this->OTLdata[$i]['uni'] == 0xFEAE || $this->OTLdata[$i]['uni'] == 0xFEF2 || $this->OTLdata[$i]['uni'] == 0xFEF0 || $this->OTLdata[$i]['uni'] == 0xFEF4 || $this->OTLdata[$i]['uni'] == 0xFBE9 || $this->OTLdata[$i]['uni'] == 0xFBFD || $this->OTLdata[$i]['uni'] == 0xFBFF + ) { + $checkpos = $i - 1; + while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + if (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == 0xFE92) { + $this->OTLdata[$checkpos]['GPOSinfo']['kashida'] = 4; // ******* Before preceding BAA + } + } // Priority 6 WAW (0648) FEEE; Ain (0639) FECA; Qaf (0642) FED6; Fa (0641) FED2 + // Final form + // Connecting to previous character + // Position: Before the character + elseif ($this->OTLdata[$i]['uni'] == 0xFEEE || $this->OTLdata[$i]['uni'] == 0xFECA || $this->OTLdata[$i]['uni'] == 0xFED6 || $this->OTLdata[$i]['uni'] == 0xFED2) { + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 3; + } + + // Priority 7 Other connecting characters + // Final form + // Connecting to previous character + // Position: Before the character + /* This isn't in the spec, but using MS WORD as a basis, give a lower priority to the 3 characters already checked + in (5) above. Test case: + خْرَىٰ + فَتُذَكِّر + */ + + if (!isset($this->OTLdata[$i]['GPOSinfo']['kashida'])) { + if (strpos($this->GSUBdata[$this->GSUBfont]['finals'], $this->OTLdata[$i]['hex']) !== false) { // ANY OTHER FINAL FORM + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 2; + } elseif (strpos('0FEAE 0FEF0 0FEF2', $this->OTLdata[$i]['hex']) !== false) { // not already included in 5 above + $this->OTLdata[$i]['GPOSinfo']['kashida'] = 1; + } + } + } + + //----------------------------------------------------------------------------------- + // d. Apply Presentation Forms GSUB Lookups (+ any discretionary) - Apply one at a time in Feature order + //----------------------------------------------------------------------------------- + $tags = 'rlig calt liga clig mset'; + + $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo'; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false); + } + + $ts = explode(' ', $usetags); + foreach ($ts as $ut) { // - Apply one at a time in Feature order + $this->_applyGSUBrules($ut, $GSUBscriptTag, $GSUBlangsys); + } + //----------------------------------------------------------------------------------- + // e. NOT IN SPEC + // If space precedes a mark -> substitute a   before the Mark, to prevent line breaking Test: + //----------------------------------------------------------------------------------- + for ($ptr = 1; $ptr < count($this->OTLdata); $ptr++) { + if ($this->OTLdata[$ptr]['general_category'] == Ucdn::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK && $this->OTLdata[$ptr - 1]['uni'] == 32) { + $this->OTLdata[$ptr - 1]['uni'] = 0xa0; + $this->OTLdata[$ptr - 1]['hex'] = '000A0'; + } + } + } // 5(I). GSUB - Shaper - INDIC and SINHALA and KHMER + //=================================== + elseif ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') { + $this->restrictToSyllable = true; + //----------------------------------------------------------------------------------- + // a. First decompose/compose split mattras + // (normalize) ??????? Nukta/Halant order etc ?????????????????????????????????????????????????????????????????????????? + //----------------------------------------------------------------------------------- + for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) { + $char = $this->OTLdata[$ptr]['uni']; + $sub = Indic::decompose_indic($char); + if ($sub) { + $newinfo = []; + for ($i = 0; $i < count($sub); $i++) { + $newinfo[$i] = []; + $ucd_record = Ucdn::get_ucd_record($sub[$i]); + $newinfo[$i]['general_category'] = $ucd_record[0]; + $newinfo[$i]['bidi_type'] = $ucd_record[2]; + $charasstr = $this->unicode_hex($sub[$i]); + if (strpos($this->GlyphClassMarks, $charasstr) !== false) { + $newinfo[$i]['group'] = 'M'; + } else { + $newinfo[$i]['group'] = 'C'; + } + $newinfo[$i]['uni'] = $sub[$i]; + $newinfo[$i]['hex'] = $charasstr; + } + array_splice($this->OTLdata, $ptr, 1, $newinfo); + $ptr += count($sub) - 1; + } + /* Only Composition-exclusion exceptions that we want to recompose. */ + if ($this->shaper == 'I') { + if ($char == 0x09AF && isset($this->OTLdata[$ptr + 1]) && $this->OTLdata[$ptr + 1]['uni'] == 0x09BC) { + $sub = 0x09DF; + $newinfo = []; + $newinfo[0] = []; + $ucd_record = Ucdn::get_ucd_record($sub); + $newinfo[0]['general_category'] = $ucd_record[0]; + $newinfo[0]['bidi_type'] = $ucd_record[2]; + $newinfo[0]['group'] = 'C'; + $newinfo[0]['uni'] = $sub; + $newinfo[0]['hex'] = $this->unicode_hex($sub); + array_splice($this->OTLdata, $ptr, 2, $newinfo); + } + } + } + //----------------------------------------------------------------------------------- + // b. Analyse characters - group as syllables/clusters (Indic); invalid diacritics; add dotted circle + //----------------------------------------------------------------------------------- + $indic_category_string = ''; + foreach ($this->OTLdata as $eid => $c) { + Indic::set_indic_properties($this->OTLdata[$eid], $scriptblock); // sets ['indic_category'] and ['indic_position'] + //$c['general_category'] + //$c['combining_class'] + //$c['uni'] = $char; + + $indic_category_string .= Indic::$indic_category_char[$this->OTLdata[$eid]['indic_category']]; + } + + $broken_syllables = false; + if ($this->shaper == 'I') { + Indic::set_syllables($this->OTLdata, $indic_category_string, $broken_syllables); + } elseif ($this->shaper == 'S') { + Indic::set_syllables_sinhala($this->OTLdata, $indic_category_string, $broken_syllables); + } elseif ($this->shaper == 'K') { + Indic::set_syllables_khmer($this->OTLdata, $indic_category_string, $broken_syllables); + } + $indic_category_string = ''; + + //----------------------------------------------------------------------------------- + // c. Initial Re-ordering (Indic / Khmer / Sinhala) + //----------------------------------------------------------------------------------- + // Find base consonant + // Decompose/compose and reorder Matras + // Reorder marks to canonical order + + $indic_config = Indic::$indic_configs[$scriptblock]; + $dottedcircle = false; + if ($broken_syllables) { + if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) { + $dottedcircle = []; + $ucd_record = Ucdn::get_ucd_record(0x25CC); + $dottedcircle[0]['general_category'] = $ucd_record[0]; + $dottedcircle[0]['bidi_type'] = $ucd_record[2]; + $dottedcircle[0]['group'] = 'C'; + $dottedcircle[0]['uni'] = 0x25CC; + $dottedcircle[0]['indic_category'] = Indic::OT_DOTTEDCIRCLE; + $dottedcircle[0]['indic_position'] = Indic::POS_BASE_C; + + $dottedcircle[0]['hex'] = '025CC'; // TEMPORARY ***** + } + } + Indic::initial_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $indic_config, $scriptblock, $is_old_spec, $dottedcircle); + + //----------------------------------------------------------------------------------- + // d. Apply initial and basic shaping forms GSUB Lookups (one at a time) + //----------------------------------------------------------------------------------- + if ($this->shaper == 'I' || $this->shaper == 'S') { + $tags = 'locl ccmp nukt akhn rphf rkrf pref blwf half pstf vatu cjct'; + } elseif ($this->shaper == 'K') { + $tags = 'locl ccmp pref blwf abvf pstf cfar'; + } + $this->_applyGSUBrulesIndic($tags, $GSUBscriptTag, $GSUBlangsys, $is_old_spec); + + //----------------------------------------------------------------------------------- + // e. Final Re-ordering (Indic / Khmer / Sinhala) + //----------------------------------------------------------------------------------- + // Reorder matras + // Reorder reph + // Reorder pre-base reordering consonants: + + Indic::final_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $indic_config, $scriptblock, $is_old_spec); + + //----------------------------------------------------------------------------------- + // f. Apply 'init' feature to first syllable in word (indicated by ['mask']) Indic::FLAG(Indic::INIT); + //----------------------------------------------------------------------------------- + if ($this->shaper == 'I' || $this->shaper == 'S') { + $tags = 'init'; + $this->_applyGSUBrulesIndic($tags, $GSUBscriptTag, $GSUBlangsys, $is_old_spec); + } + + //----------------------------------------------------------------------------------- + // g. Apply Presentation Forms GSUB Lookups (+ any discretionary) + //----------------------------------------------------------------------------------- + $tags = 'pres abvs blws psts haln rlig calt liga clig mset'; + + $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo'; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false); + } + if ($this->shaper == 'K') { // Features are applied one at a time, working through each codepoint + $this->_applyGSUBrulesSingly($usetags, $GSUBscriptTag, $GSUBlangsys); + } else { + $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys); + } + $this->restrictToSyllable = false; + } // 5(M). GSUB - Shaper - MYANMAR (ONLY mym2) + //============================== + // NB Old style 'mymr' is left to go through the default shaper + elseif ($this->shaper == 'M') { + $this->restrictToSyllable = true; + //----------------------------------------------------------------------------------- + // a. Analyse characters - group as syllables/clusters (Myanmar); invalid diacritics; add dotted circle + //----------------------------------------------------------------------------------- + $myanmar_category_string = ''; + foreach ($this->OTLdata as $eid => $c) { + Myanmar::set_myanmar_properties($this->OTLdata[$eid]); // sets ['myanmar_category'] and ['myanmar_position'] + $myanmar_category_string .= Myanmar::$myanmar_category_char[$this->OTLdata[$eid]['myanmar_category']]; + } + $broken_syllables = false; + Myanmar::set_syllables($this->OTLdata, $myanmar_category_string, $broken_syllables); + $myanmar_category_string = ''; + + //----------------------------------------------------------------------------------- + // b. Re-ordering (Myanmar mym2) + //----------------------------------------------------------------------------------- + $dottedcircle = false; + if ($broken_syllables) { + if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) { + $dottedcircle = []; + $ucd_record = Ucdn::get_ucd_record(0x25CC); + $dottedcircle[0]['general_category'] = $ucd_record[0]; + $dottedcircle[0]['bidi_type'] = $ucd_record[2]; + $dottedcircle[0]['group'] = 'C'; + $dottedcircle[0]['uni'] = 0x25CC; + $dottedcircle[0]['myanmar_category'] = Myanmar::OT_DOTTEDCIRCLE; + $dottedcircle[0]['myanmar_position'] = Myanmar::POS_BASE_C; + $dottedcircle[0]['hex'] = '025CC'; + } + } + Myanmar::reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $dottedcircle); + + //----------------------------------------------------------------------------------- + // c. Apply initial and basic shaping forms GSUB Lookups (one at a time) + //----------------------------------------------------------------------------------- + + $tags = 'locl ccmp rphf pref blwf pstf'; + $this->_applyGSUBrulesMyanmar($tags, $GSUBscriptTag, $GSUBlangsys); + + //----------------------------------------------------------------------------------- + // d. Apply Presentation Forms GSUB Lookups (+ any discretionary) + //----------------------------------------------------------------------------------- + $tags = 'pres abvs blws psts haln rlig calt liga clig mset'; + $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo'; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false); + } + $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys); + $this->restrictToSyllable = false; + } // 5(E). GSUB - Shaper - SEA South East Asian (New Tai Lue, Cham, Tai Tam) + //============================== + elseif ($this->shaper == 'E') { + /* HarfBuzz says: If the designer designed the font for the 'DFLT' script, + * use the default shaper. Otherwise, use the SEA shaper. + * Note that for some simple scripts, there may not be *any* + * GSUB/GPOS needed, so there may be no scripts found! */ + + $this->restrictToSyllable = true; + //----------------------------------------------------------------------------------- + // a. Analyse characters - group as syllables/clusters (Indic); invalid diacritics; add dotted circle + //----------------------------------------------------------------------------------- + $sea_category_string = ''; + foreach ($this->OTLdata as $eid => $c) { + Sea::set_sea_properties($this->OTLdata[$eid], $scriptblock); // sets ['sea_category'] and ['sea_position'] + //$c['general_category'] + //$c['combining_class'] + //$c['uni'] = $char; + + $sea_category_string .= Sea::$sea_category_char[$this->OTLdata[$eid]['sea_category']]; + } + + $broken_syllables = false; + Sea::set_syllables($this->OTLdata, $sea_category_string, $broken_syllables); + $sea_category_string = ''; + + //----------------------------------------------------------------------------------- + // b. Apply locl and ccmp shaping forms - before initial re-ordering; GSUB Lookups (one at a time) + //----------------------------------------------------------------------------------- + $tags = 'locl ccmp'; + $this->_applyGSUBrulesSingly($tags, $GSUBscriptTag, $GSUBlangsys); + + //----------------------------------------------------------------------------------- + // c. Initial Re-ordering + //----------------------------------------------------------------------------------- + // Find base consonant + // Decompose/compose and reorder Matras + // Reorder marks to canonical order + + $dottedcircle = false; + if ($broken_syllables) { + if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) { + $dottedcircle = []; + $ucd_record = Ucdn::get_ucd_record(0x25CC); + $dottedcircle[0]['general_category'] = $ucd_record[0]; + $dottedcircle[0]['bidi_type'] = $ucd_record[2]; + $dottedcircle[0]['group'] = 'C'; + $dottedcircle[0]['uni'] = 0x25CC; + $dottedcircle[0]['sea_category'] = Sea::OT_GB; + $dottedcircle[0]['sea_position'] = Sea::POS_BASE_C; + + $dottedcircle[0]['hex'] = '025CC'; // TEMPORARY ***** + } + } + Sea::initial_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $scriptblock, $dottedcircle); + + //----------------------------------------------------------------------------------- + // d. Apply basic shaping forms GSUB Lookups (one at a time) + //----------------------------------------------------------------------------------- + $tags = 'pref abvf blwf pstf'; + $this->_applyGSUBrulesSingly($tags, $GSUBscriptTag, $GSUBlangsys); + + //----------------------------------------------------------------------------------- + // e. Final Re-ordering + //----------------------------------------------------------------------------------- + + Sea::final_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $scriptblock); + + //----------------------------------------------------------------------------------- + // f. Apply Presentation Forms GSUB Lookups (+ any discretionary) + //----------------------------------------------------------------------------------- + $tags = 'pres abvs blws psts'; + + $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo'; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false); + } + $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys); + $this->restrictToSyllable = false; + } // 5(D). GSUB - Shaper - DEFAULT (including THAI and LAO and MYANMAR v1 [mymr] and TIBETAN) + //============================== + else { // DEFAULT + //----------------------------------------------------------------------------------- + // a. First decompose/compose in Thai / Lao - Tibetan + //----------------------------------------------------------------------------------- + // Decomposition for THAI or LAO + /* This function implements the shaping logic documented here: + * + * http://linux.thai.net/~thep/th-otf/shaping.html + * + * The first shaping rule listed there is needed even if the font has Thai + * OpenType tables. + * + * + * The following is NOT specified in the MS OT Thai spec, however, it seems + * to be what Uniscribe and other engines implement. According to Eric Muller: + * + * When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the + * NIKHAHIT backwards over any tone mark (0E48-0E4B). + * + * <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32> + * + * This reordering is legit only when the NIKHAHIT comes from a SARA AM, not + * when it's there to start with. The string <0E14, 0E4B, 0E4D> is probably + * not what a user wanted, but the rendering is nevertheless nikhahit above + * chattawa. + * + * Same for Lao. + * + * Thai Lao + * SARA AM: U+0E33 U+0EB3 + * SARA AA: U+0E32 U+0EB2 + * Nikhahit: U+0E4D U+0ECD + * + * Testing shows that Uniscribe reorder the following marks: + * Thai: <0E31,0E34..0E37,0E47..0E4E> + * Lao: <0EB1,0EB4..0EB7,0EC7..0ECE> + * + * Lao versions are the same as Thai + 0x80. + */ + if ($this->shaper == 'T' || $this->shaper == 'L') { + for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) { + $char = $this->OTLdata[$ptr]['uni']; + if (($char & ~0x0080) == 0x0E33) { // if SARA_AM (U+0E33 or U+0EB3) + $NIKHAHIT = $char + 0x1A; + $SARA_AA = $char - 1; + $sub = [$SARA_AA, $NIKHAHIT]; + + $newinfo = []; + $ucd_record = Ucdn::get_ucd_record($sub[0]); + $newinfo[0]['general_category'] = $ucd_record[0]; + $newinfo[0]['bidi_type'] = $ucd_record[2]; + $charasstr = $this->unicode_hex($sub[0]); + if (strpos($this->GlyphClassMarks, $charasstr) !== false) { + $newinfo[0]['group'] = 'M'; + } else { + $newinfo[0]['group'] = 'C'; + } + $newinfo[0]['uni'] = $sub[0]; + $newinfo[0]['hex'] = $charasstr; + $this->OTLdata[$ptr] = $newinfo[0]; // Substitute SARA_AM => SARA_AA + + $ntones = 0; // number of (preceding) tone marks + // IS_TONE_MARK ((x) & ~0x0080, 0x0E34 - 0x0E37, 0x0E47 - 0x0E4E, 0x0E31) + while (isset($this->OTLdata[$ptr - 1 - $ntones]) && ( + ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) == 0x0E31 || + (($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) >= 0x0E34 && + ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) <= 0x0E37) || + (($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) >= 0x0E47 && + ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) <= 0x0E4E) + ) + ) { + $ntones++; + } + + $newinfo = []; + $ucd_record = Ucdn::get_ucd_record($sub[1]); + $newinfo[0]['general_category'] = $ucd_record[0]; + $newinfo[0]['bidi_type'] = $ucd_record[2]; + $charasstr = $this->unicode_hex($sub[1]); + if (strpos($this->GlyphClassMarks, $charasstr) !== false) { + $newinfo[0]['group'] = 'M'; + } else { + $newinfo[0]['group'] = 'C'; + } + $newinfo[0]['uni'] = $sub[1]; + $newinfo[0]['hex'] = $charasstr; + // Insert NIKAHIT + array_splice($this->OTLdata, $ptr - $ntones, 0, $newinfo); + + $ptr++; + } + } + } + + if ($scriptblock == Ucdn::SCRIPT_TIBETAN) { + // ========================= + // Reordering TIBETAN + // ========================= + // Tibetan does not need to need a shaper generally, as long as characters are presented in the correct order + // so we will do one minor change here: + // From ICU: If the present character is a number, and the next character is a pre-number combining mark + // then the two characters are reordered + // From MS OTL spec the following are Digit modifiers (Md): 0F18–0F19, 0F3E–0F3F + // Digits: 0F20–0F33 + // On testing only 0x0F3F (pre-based mark) seems to need re-ordering + for ($ptr = 0; $ptr < count($this->OTLdata) - 1; $ptr++) { + if (Indic::in_range($this->OTLdata[$ptr]['uni'], 0x0F20, 0x0F33) && $this->OTLdata[$ptr + 1]['uni'] == 0x0F3F) { + $tmp = $this->OTLdata[$ptr + 1]; + $this->OTLdata[$ptr + 1] = $this->OTLdata[$ptr]; + $this->OTLdata[$ptr] = $tmp; + } + } + + + // ========================= + // Decomposition for TIBETAN + // ========================= + /* Recommended, but does not seem to change anything... + for($ptr=0; $ptr<count($this->OTLdata); $ptr++) { + $char = $this->OTLdata[$ptr]['uni']; + $sub = Indic::decompose_indic($char); + if ($sub) { + $newinfo = array(); + for($i=0;$i<count($sub);$i++) { + $newinfo[$i] = array(); + $ucd_record = Ucdn::get_ucd_record($sub[$i]); + $newinfo[$i]['general_category'] = $ucd_record[0]; + $newinfo[$i]['bidi_type'] = $ucd_record[2]; + $charasstr = $this->unicode_hex($sub[$i]); + if (strpos($this->GlyphClassMarks, $charasstr)!==false) { $newinfo[$i]['group'] = 'M'; } + else { $newinfo[$i]['group'] = 'C'; } + $newinfo[$i]['uni'] = $sub[$i]; + $newinfo[$i]['hex'] = $charasstr; + } + array_splice($this->OTLdata, $ptr, 1, $newinfo); + $ptr += count($sub)-1; + } + } + */ + } + + + //----------------------------------------------------------------------------------- + // b. Apply all GSUB Lookups (in order specified in lookup list) + //----------------------------------------------------------------------------------- + $tags = 'locl ccmp pref blwf abvf pstf pres abvs blws psts haln rlig calt liga clig mset RQD'; + // pref blwf abvf pstf required for Tibetan + // " RQD" is a non-standard tag in Garuda font - presumably intended to be used by default ? "ReQuireD" + // Being a 3 letter tag is non-standard, and does not allow it to be set by font-feature-settings + + + /* ?Add these until shapers witten? + Hangul: ljmo vjmo tjmo + */ + + $omittags = ''; + $useGSUBtags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $useGSUBtags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false); + } + // APPLY GSUB rules (as long as not Latin + SmallCaps - but not OTL smcp) + if (!(($this->mpdf->textvar & TextVars::FC_SMALLCAPS) && $scriptblock == Ucdn::SCRIPT_LATIN && strpos($useGSUBtags, 'smcp') === false)) { + $this->_applyGSUBrules($useGSUBtags, $GSUBscriptTag, $GSUBlangsys); + } + } + } + + // Shapers - KHMER & THAI & LAO - Replace Word boundary marker with U+200B + // Also TIBETAN (no shaper) + //======================================================= + if (($this->shaper == "K" || $this->shaper == "T" || $this->shaper == "L") || $scriptblock == Ucdn::SCRIPT_TIBETAN) { + // Set up properties to insert a U+200B character + $newinfo = []; + //$newinfo[0] = array('general_category' => 1, 'bidi_type' => 14, 'group' => 'S', 'uni' => 0x200B, 'hex' => '0200B'); + $newinfo[0] = [ + 'general_category' => Ucdn::UNICODE_GENERAL_CATEGORY_FORMAT, + 'bidi_type' => Ucdn::BIDI_CLASS_BN, + 'group' => 'S', 'uni' => 0x200B, 'hex' => '0200B']; + // Then insert U+200B at (after) all word end boundaries + for ($i = count($this->OTLdata) - 1; $i > 0; $i--) { + // Make sure after GSUB that wordend has not been moved - check next char is not in the same syllable + if (isset($this->OTLdata[$i]['wordend']) && $this->OTLdata[$i]['wordend'] && + isset($this->OTLdata[$i + 1]['uni']) && (!isset($this->OTLdata[$i + 1]['syllable']) || !isset($this->OTLdata[$i + 1]['syllable']) || $this->OTLdata[$i + 1]['syllable'] != $this->OTLdata[$i]['syllable'])) { + array_splice($this->OTLdata, $i + 1, 0, $newinfo); + $this->_updateLigatureMarks($i, 1); + } elseif ($this->OTLdata[$i]['uni'] == 0x2e) { // Word end if Full-stop. + array_splice($this->OTLdata, $i + 1, 0, $newinfo); + $this->_updateLigatureMarks($i, 1); + } + } + } + + + // Shapers - INDIC & ARABIC & KHMER & SINHALA & MYANMAR - Remove ZWJ and ZWNJ + //======================================================= + if ($this->shaper == 'I' || $this->shaper == 'S' || $this->shaper == 'A' || $this->shaper == 'K' || $this->shaper == 'M') { + // Remove ZWJ and ZWNJ + for ($i = 0; $i < count($this->OTLdata); $i++) { + if ($this->OTLdata[$i]['uni'] == 8204 || $this->OTLdata[$i]['uni'] == 8205) { + array_splice($this->OTLdata, $i, 1); + $this->_updateLigatureMarks($i, -1); + } + } + } + + + //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + ////////// GPOS ///////////////////////////////// + //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + if (($useOTL & 0xFF) && $GPOSscriptTag && $GPOSlangsys && $GPOSFeatures) { + $this->Entry = []; + $this->Exit = []; + + // 6. Load GPOS data, Coverage & Lookups + //================================================================= + $fontCacheFilename = $this->mpdf->CurrentFont['fontkey'] . '.GPOSdata.json'; + if (!isset($this->GPOSdata[$this->fontkey]) && $this->fontCache->jsonHas($fontCacheFilename)) { + $this->LuCoverage = $this->GPOSdata[$this->fontkey]['LuCoverage'] = $this->fontCache->jsonLoad($fontCacheFilename); + } else { + $this->LuCoverage = $this->GPOSdata[$this->fontkey]['LuCoverage']; + } + + $this->GPOSLookups = $this->mpdf->CurrentFont['GPOSLookups']; + + + // 7. Select Feature tags to use (incl optional) + //============================== + $tags = 'abvm blwm mark mkmk curs cpsp dist requ'; // Default set + // 'requ' is not listed in the Microsoft registry of Feature tags + // Found in Arial Unicode MS, it repositions the baseline for punctuation in Kannada script + + // ZZZ96 + // Set kern to be included by default in non-Latin script (? just when shapers used) + // Kern is used in some fonts to reposition marks etc. and is essential for correct display + //if ($this->shaper) {$tags .= ' kern'; } + if ($scriptblock != Ucdn::SCRIPT_LATIN) { + $tags .= ' kern'; + } + + $omittags = ''; + $usetags = $tags; + if (!empty($this->mpdf->OTLtags)) { + $usetags = $this->_applyTagSettings($tags, $GPOSFeatures, $omittags, false); + } + + + + // 8. Get GPOS LookupList from Feature tags + //============================== + $LookupList = []; + foreach ($GPOSFeatures as $tag => $arr) { + if (strpos($usetags, $tag) !== false) { + foreach ($arr as $lu) { + $LookupList[$lu] = $tag; + } + } + } + ksort($LookupList); + + + // 9. Apply GPOS Lookups (in order specified in lookup list but selecting from specified tags) + //============================== + // APPLY THE GPOS RULES (as long as not Latin + SmallCaps - but not OTL smcp) + if (!(($this->mpdf->textvar & TextVars::FC_SMALLCAPS) && $scriptblock == Ucdn::SCRIPT_LATIN && strpos($useGSUBtags, 'smcp') === false)) { + $this->_applyGPOSrules($LookupList, $is_old_spec); + // (sets: $this->OTLdata[n]['GPOSinfo'] XPlacement YPlacement XAdvance Entry Exit ) + } + + // 10. Process cursive text + //============================== + if (count($this->Entry) || count($this->Exit)) { + // RTL + $incurs = false; + for ($i = (count($this->OTLdata) - 1); $i >= 0; $i--) { + if (isset($this->Entry[$i]) && isset($this->Entry[$i]['Y']) && $this->Entry[$i]['dir'] == 'RTL') { + $nextbase = $i - 1; // Set as next base ignoring marks (next base reading RTL in logical oder + while (isset($this->OTLdata[$nextbase]['hex']) && strpos($this->GlyphClassMarks, $this->OTLdata[$nextbase]['hex']) !== false) { + $nextbase--; + } + if (isset($this->Exit[$nextbase]) && isset($this->Exit[$nextbase]['Y'])) { + $diff = $this->Entry[$i]['Y'] - $this->Exit[$nextbase]['Y']; + if ($incurs === false) { + $incurs = $diff; + } else { + $incurs += $diff; + } + for ($j = ($i - 1); $j >= $nextbase; $j--) { + if (isset($this->OTLdata[$j]['GPOSinfo']['YPlacement'])) { + $this->OTLdata[$j]['GPOSinfo']['YPlacement'] += $incurs; + } else { + $this->OTLdata[$j]['GPOSinfo']['YPlacement'] = $incurs; + } + } + if (isset($this->Exit[$i]['X']) && isset($this->Entry[$nextbase]['X'])) { + $adj = -($this->Entry[$i]['X'] - $this->Exit[$nextbase]['X']); + // If XAdvance is aplied - in order for PDF to position the Advance correctly need to place it on: + // in RTL - the current glyph or the last of any associated marks + if (isset($this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'])) { + $this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'] += $adj; + } else { + $this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'] = $adj; + } + } + } else { + $incurs = false; + } + } elseif (strpos($this->GlyphClassMarks, $this->OTLdata[$i]['hex']) !== false) { + continue; + } // ignore Marks + else { + $incurs = false; + } + } + // LTR + $incurs = false; + for ($i = 0; $i < count($this->OTLdata); $i++) { + if (isset($this->Exit[$i]) && isset($this->Exit[$i]['Y']) && $this->Exit[$i]['dir'] == 'LTR') { + $nextbase = $i + 1; // Set as next base ignoring marks + while (strpos($this->GlyphClassMarks, $this->OTLdata[$nextbase]['hex']) !== false) { + $nextbase++; + } + if (isset($this->Entry[$nextbase]) && isset($this->Entry[$nextbase]['Y'])) { + $diff = $this->Exit[$i]['Y'] - $this->Entry[$nextbase]['Y']; + if ($incurs === false) { + $incurs = $diff; + } else { + $incurs += $diff; + } + for ($j = ($i + 1); $j <= $nextbase; $j++) { + if (isset($this->OTLdata[$j]['GPOSinfo']['YPlacement'])) { + $this->OTLdata[$j]['GPOSinfo']['YPlacement'] += $incurs; + } else { + $this->OTLdata[$j]['GPOSinfo']['YPlacement'] = $incurs; + } + } + if (isset($this->Exit[$i]['X']) && isset($this->Entry[$nextbase]['X'])) { + $adj = -($this->Exit[$i]['X'] - $this->Entry[$nextbase]['X']); + // If XAdvance is aplied - in order for PDF to position the Advance correctly need to place it on: + // in LTR - the next glyph, ignoring marks + if (isset($this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'])) { + $this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'] += $adj; + } else { + $this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'] = $adj; + } + } + } else { + $incurs = false; + } + } elseif (strpos($this->GlyphClassMarks, $this->OTLdata[$i]['hex']) !== false) { + continue; + } // ignore Marks + else { + $incurs = false; + } + } + } + } // end GPOS + + if ($this->debugOTL) { + $this->_dumpproc('END', '-', '-', '-', '-', 0, '-', 0); + exit; + } + + $this->schOTLdata[$sch] = $this->OTLdata; + $this->OTLdata = []; + } // END foreach subchunk + // 11. Re-assemble and return text string + //============================== + $newGPOSinfo = []; + $newOTLdata = []; + $newchar_data = []; + $newgroup = ''; + $e = ''; + $ectr = 0; + + for ($sch = 0; $sch <= $subchunk; $sch++) { + for ($i = 0; $i < count($this->schOTLdata[$sch]); $i++) { + if (isset($this->schOTLdata[$sch][$i]['GPOSinfo'])) { + $newGPOSinfo[$ectr] = $this->schOTLdata[$sch][$i]['GPOSinfo']; + } + $newchar_data[$ectr] = ['bidi_class' => $this->schOTLdata[$sch][$i]['bidi_type'], 'uni' => $this->schOTLdata[$sch][$i]['uni']]; + $newgroup .= $this->schOTLdata[$sch][$i]['group']; + $e .= UtfString::code2utf($this->schOTLdata[$sch][$i]['uni']); + if (isset($this->mpdf->CurrentFont['subset'])) { + $this->mpdf->CurrentFont['subset'][$this->schOTLdata[$sch][$i]['uni']] = $this->schOTLdata[$sch][$i]['uni']; + } + $ectr++; + } + } + $this->OTLdata['GPOSinfo'] = $newGPOSinfo; + $this->OTLdata['char_data'] = $newchar_data; + $this->OTLdata['group'] = $newgroup; + + // This leaves OTLdata::GPOSinfo, ::bidi_type, & ::group + + return $e; + } + + function _applyTagSettings($tags, $Features, $omittags = '', $onlytags = false) + { + if (empty($this->mpdf->OTLtags['Plus']) && empty($this->mpdf->OTLtags['Minus']) && empty($this->mpdf->OTLtags['FFPlus']) && empty($this->mpdf->OTLtags['FFMinus'])) { + return $tags; + } + + // Use $tags as starting point + $usetags = $tags; + + // Only set / unset tags which are in the font + // Ignore tags which are in $omittags + // If $onlytags, then just unset tags which are already in the Tag list + + $fp = $fm = $ffp = $ffm = ''; + + // Font features to enable - set by font-variant-xx + if (isset($this->mpdf->OTLtags['Plus'])) { + $fp = $this->mpdf->OTLtags['Plus']; + } + preg_match_all('/([a-zA-Z0-9]{4})/', $fp, $m); + for ($i = 0; $i < count($m[0]); $i++) { + $t = $m[1][$i]; + // Is it a valid tag? + if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) { + $usetags .= ' ' . $t; + } + } + + // Font features to disable - set by font-variant-xx + if (isset($this->mpdf->OTLtags['Minus'])) { + $fm = $this->mpdf->OTLtags['Minus']; + } + preg_match_all('/([a-zA-Z0-9]{4})/', $fm, $m); + for ($i = 0; $i < count($m[0]); $i++) { + $t = $m[1][$i]; + // Is it a valid tag? + if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) { + $usetags = str_replace($t, '', $usetags); + } + } + + // Font features to enable - set by font-feature-settings + if (isset($this->mpdf->OTLtags['FFPlus'])) { + $ffp = $this->mpdf->OTLtags['FFPlus']; // Font Features - may include integer: salt4 + } + preg_match_all('/([a-zA-Z0-9]{4})([\d+]*)/', $ffp, $m); + for ($i = 0; $i < count($m[0]); $i++) { + $t = $m[1][$i]; + // Is it a valid tag? + if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) { + $usetags .= ' ' . $m[0][$i]; // - may include integer: salt4 + } + } + + // Font features to disable - set by font-feature-settings + if (isset($this->mpdf->OTLtags['FFMinus'])) { + $ffm = $this->mpdf->OTLtags['FFMinus']; + } + preg_match_all('/([a-zA-Z0-9]{4})/', $ffm, $m); + for ($i = 0; $i < count($m[0]); $i++) { + $t = $m[1][$i]; + // Is it a valid tag? + if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) { + $usetags = str_replace($t, '', $usetags); + } + } + return $usetags; + } + + function _applyGSUBrules($usetags, $scriptTag, $langsys) + { + // Features from all Tags are applied together, in Lookup List order. + // For Indic - should be applied one syllable at a time + // - Implemented in functions checkContextMatch and checkContextMatchMultiple by failing to match if outside scope of current 'syllable' + // if $this->restrictToSyllable is true + + $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys]; + $LookupList = []; + foreach ($GSUBFeatures as $tag => $arr) { + if (strpos($usetags, $tag) !== false) { + foreach ($arr as $lu) { + $LookupList[$lu] = $tag; + } + } + } + ksort($LookupList); + + foreach ($LookupList as $lu => $tag) { + $Type = $this->GSUBLookups[$lu]['Type']; + $Flag = $this->GSUBLookups[$lu]['Flag']; + $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + $tagInt = 1; + if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) { + $tagInt = $m[1]; + } + $ptr = 0; + // Test each glyph sequentially + while ($ptr < (count($this->OTLdata))) { // whilst there is another glyph ..0064 + $currGlyph = $this->OTLdata[$ptr]['hex']; + $currGID = $this->OTLdata[$ptr]['uni']; + $shift = 1; + foreach ($this->GSUBLookups[$lu]['Subtables'] as $c => $subtable_offset) { + // NB Coverage only looks at glyphs for position 1 (esp. 7.3 and 8.3) + if (isset($this->GSLuCoverage[$lu][$c][$currGID])) { + // Get rules from font GSUB subtable + $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $tag, 0, $tagInt); + + if ($shift) { + break; + } + } + } + if ($shift == 0) { + $shift = 1; + } + $ptr += $shift; + } + } + } + + function _applyGSUBrulesSingly($usetags, $scriptTag, $langsys) + { + // Features are applied one at a time, working through each codepoint + + $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys]; + + $tags = explode(' ', $usetags); + foreach ($tags as $usetag) { + $LookupList = []; + foreach ($GSUBFeatures as $tag => $arr) { + if (strpos($usetags, $tag) !== false) { + foreach ($arr as $lu) { + $LookupList[$lu] = $tag; + } + } + } + ksort($LookupList); + + $ptr = 0; + // Test each glyph sequentially + while ($ptr < (count($this->OTLdata))) { // whilst there is another glyph ..0064 + $currGlyph = $this->OTLdata[$ptr]['hex']; + $currGID = $this->OTLdata[$ptr]['uni']; + $shift = 1; + + foreach ($LookupList as $lu => $tag) { + $Type = $this->GSUBLookups[$lu]['Type']; + $Flag = $this->GSUBLookups[$lu]['Flag']; + $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + $tagInt = 1; + if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) { + $tagInt = $m[1]; + } + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $c => $subtable_offset) { + // NB Coverage only looks at glyphs for position 1 (esp. 7.3 and 8.3) + if (isset($this->GSLuCoverage[$lu][$c][$currGID])) { + // Get rules from font GSUB subtable + $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $tag, 0, $tagInt); + + if ($shift) { + break 2; + } + } + } + } + if ($shift == 0) { + $shift = 1; + } + $ptr += $shift; + } + } + } + + function _applyGSUBrulesMyanmar($usetags, $scriptTag, $langsys) + { + // $usetags = locl ccmp rphf pref blwf pstf'; + // applied to all characters + + $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys]; + + // ALL should be applied one syllable at a time + // Implemented in functions checkContextMatch and checkContextMatchMultiple by failing to match if outside scope of current 'syllable' + $tags = explode(' ', $usetags); + foreach ($tags as $usetag) { + $LookupList = []; + foreach ($GSUBFeatures as $tag => $arr) { + if ($tag == $usetag) { + foreach ($arr as $lu) { + $LookupList[$lu] = $tag; + } + } + } + ksort($LookupList); + + foreach ($LookupList as $lu => $tag) { + $Type = $this->GSUBLookups[$lu]['Type']; + $Flag = $this->GSUBLookups[$lu]['Flag']; + $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + $tagInt = 1; + if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) { + $tagInt = $m[1]; + } + + $ptr = 0; + // Test each glyph sequentially + while ($ptr < (count($this->OTLdata))) { // whilst there is another glyph ..0064 + $currGlyph = $this->OTLdata[$ptr]['hex']; + $currGID = $this->OTLdata[$ptr]['uni']; + $shift = 1; + foreach ($this->GSUBLookups[$lu]['Subtables'] as $c => $subtable_offset) { + // NB Coverage only looks at glyphs for position 1 (esp. 7.3 and 8.3) + if (isset($this->GSLuCoverage[$lu][$c][$currGID])) { + // Get rules from font GSUB subtable + $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $usetag, 0, $tagInt); + + if ($shift) { + break; + } + } + } + if ($shift == 0) { + $shift = 1; + } + $ptr += $shift; + } + } + } + } + + function _applyGSUBrulesIndic($usetags, $scriptTag, $langsys, $is_old_spec) + { + // $usetags = 'locl ccmp nukt akhn rphf rkrf pref blwf half pstf vatu cjct'; then later - init + // rphf, pref, blwf, half, abvf, pstf, and init are only applied where ['mask'] indicates: Indic::FLAG(Indic::RPHF); + // The rest are applied to all characters + + $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys]; + + // ALL should be applied one syllable at a time + // Implemented in functions checkContextMatch and checkContextMatchMultiple by failing to match if outside scope of current 'syllable' + $tags = explode(' ', $usetags); + foreach ($tags as $usetag) { + $LookupList = []; + foreach ($GSUBFeatures as $tag => $arr) { + if ($tag == $usetag) { + foreach ($arr as $lu) { + $LookupList[$lu] = $tag; + } + } + } + ksort($LookupList); + + foreach ($LookupList as $lu => $tag) { + $Type = $this->GSUBLookups[$lu]['Type']; + $Flag = $this->GSUBLookups[$lu]['Flag']; + $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + $tagInt = 1; + if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) { + $tagInt = $m[1]; + } + + $ptr = 0; + // Test each glyph sequentially + while ($ptr < (count($this->OTLdata))) { // whilst there is another glyph ..0064 + $currGlyph = $this->OTLdata[$ptr]['hex']; + $currGID = $this->OTLdata[$ptr]['uni']; + $shift = 1; + foreach ($this->GSUBLookups[$lu]['Subtables'] as $c => $subtable_offset) { + // NB Coverage only looks at glyphs for position 1 (esp. 7.3 and 8.3) + if (isset($this->GSLuCoverage[$lu][$c][$currGID])) { + if (strpos('rphf pref blwf half pstf cfar init', $usetag) !== false) { // only apply when mask indicates + $mask = 0; + switch ($usetag) { + case 'rphf': + $mask = (1 << (Indic::RPHF)); + break; + case 'pref': + $mask = (1 << (Indic::PREF)); + break; + case 'blwf': + $mask = (1 << (Indic::BLWF)); + break; + case 'half': + $mask = (1 << (Indic::HALF)); + break; + case 'pstf': + $mask = (1 << (Indic::PSTF)); + break; + case 'cfar': + $mask = (1 << (Indic::CFAR)); + break; + case 'init': + $mask = (1 << (Indic::INIT)); + break; + } + if (!($this->OTLdata[$ptr]['mask'] & $mask)) { + continue; + } + } + // Get rules from font GSUB subtable + $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $usetag, $is_old_spec, $tagInt); + + if ($shift) { + break; + } + } // Special case for Indic ZZZ99S + // Check to substitute Halant-Consonant in PREF, BLWF or PSTF + // i.e. new spec but GSUB tables have Consonant-Halant in Lookups e.g. FreeSerif, which + // incorrectly just moved old spec tables to new spec. Uniscribe seems to cope with this + // See also ttffontsuni.php + // First check if current glyph is a Halant/Virama + elseif (static::_OTL_OLD_SPEC_COMPAT_1 && $Type == 4 && !$is_old_spec && strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', $currGlyph) !== false) { + // only apply when 'pref blwf pstf' tags, and when mask indicates + if (strpos('pref blwf pstf', $usetag) !== false) { + $mask = 0; + switch ($usetag) { + case 'pref': + $mask = (1 << (Indic::PREF)); + break; + case 'blwf': + $mask = (1 << (Indic::BLWF)); + break; + case 'pstf': + $mask = (1 << (Indic::PSTF)); + break; + } + if (!($this->OTLdata[$ptr]['mask'] & $mask)) { + continue; + } + + if (!isset($this->OTLdata[$ptr + 1])) { + continue; + } + + $nextGlyph = $this->OTLdata[$ptr + 1]['hex']; + $nextGID = $this->OTLdata[$ptr + 1]['uni']; + if (isset($this->GSLuCoverage[$lu][$c][$nextGID])) { + // Get rules from font GSUB subtable + $shift = $this->_applyGSUBsubtableSpecial($lu, $c, $ptr, $currGlyph, $currGID, $nextGlyph, $nextGID, ($subtable_offset - $this->GSUB_offset), $Type, $this->GSLuCoverage[$lu][$c]); + + if ($shift) { + break; + } + } + } + } + } + if ($shift == 0) { + $shift = 1; + } + $ptr += $shift; + } + } + } + } + + function _applyGSUBsubtableSpecial($lookupID, $subtable, $ptr, $currGlyph, $currGID, $nextGlyph, $nextGID, $subtable_offset, $Type, $LuCoverage) + { + + // Special case for Indic + // Check to substitute Halant-Consonant in PREF, BLWF or PSTF + // i.e. new spec but GSUB tables have Consonant-Halant in Lookups e.g. FreeSerif, which + // incorrectly just moved old spec tables to new spec. Uniscribe seems to cope with this + // See also ttffontsuni.php + + $this->seek($subtable_offset); + $SubstFormat = $this->read_ushort(); + + // Subtable contains Consonant - Halant + // Text string contains Halant ($CurrGlyph) - Consonant ($nextGlyph) + // Halant has already been matched, and already checked that $nextGID is in Coverage table + //////////////////////////////////////////////////////////////////////////////// + // Only does: LookupType 4: Ligature Substitution Subtable : n to 1 + //////////////////////////////////////////////////////////////////////////////// + $Coverage = $subtable_offset + $this->read_ushort(); + $NextGlyphPos = $LuCoverage[$nextGID]; + $LigSetCount = $this->read_short(); + + $this->skip($NextGlyphPos * 2); + $LigSet = $subtable_offset + $this->read_short(); + + $this->seek($LigSet); + $LigCount = $this->read_short(); + // LigatureSet i.e. all starting with the same Glyph $nextGlyph [Consonant] + $LigatureOffset = []; + for ($g = 0; $g < $LigCount; $g++) { + $LigatureOffset[$g] = $LigSet + $this->read_ushort(); + } + for ($g = 0; $g < $LigCount; $g++) { + // Ligature tables + $this->seek($LigatureOffset[$g]); + $LigGlyph = $this->read_ushort(); + $substitute = $this->glyphToChar($LigGlyph); + $CompCount = $this->read_ushort(); + + if ($CompCount != 2) { + return 0; + } // Only expecting to work with 2:1 (and no ignore characters in between) + + + $gid = $this->read_ushort(); + $checkGlyph = $this->glyphToChar($gid); // Other component/input Glyphs starting at position 2 (arrayindex 1) + + if ($currGID == $checkGlyph) { + $match = true; + } else { + $match = false; + break; + } + + $GlyphPos = []; + $GlyphPos[] = $ptr; + $GlyphPos[] = $ptr + 1; + + + if ($match) { + $shift = $this->GSUBsubstitute($ptr, $substitute, 4, $GlyphPos); // GlyphPos contains positions to set null + if ($shift) { + return 1; + } + } + } + return 0; + } + + function _applyGSUBsubtable($lookupID, $subtable, $ptr, $currGlyph, $currGID, $subtable_offset, $Type, $Flag, $MarkFilteringSet, $LuCoverage, $level, $currentTag, $is_old_spec, $tagInt) + { + $ignore = $this->_getGCOMignoreString($Flag, $MarkFilteringSet); + + // Lets start + $this->seek($subtable_offset); + $SubstFormat = $this->read_ushort(); + + //////////////////////////////////////////////////////////////////////////////// + // LookupType 1: Single Substitution Subtable : 1 to 1 + //////////////////////////////////////////////////////////////////////////////// + if ($Type == 1) { + // Flag = Ignore + if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) { + return 0; + } + $CoverageOffset = $subtable_offset + $this->read_ushort(); + $GlyphPos = $LuCoverage[$currGID]; + //=========== + // Format 1: + //=========== + if ($SubstFormat == 1) { // Calculated output glyph indices + $DeltaGlyphID = $this->read_short(); + $this->seek($CoverageOffset); + $glyphs = $this->_getCoverageGID(); + $GlyphID = $glyphs[$GlyphPos] + $DeltaGlyphID; + } //=========== + // Format 2: + //=========== + elseif ($SubstFormat == 2) { // Specified output glyph indices + $GlyphCount = $this->read_ushort(); + $this->skip($GlyphPos * 2); + $GlyphID = $this->read_ushort(); + } + + $substitute = $this->glyphToChar($GlyphID); + $shift = $this->GSUBsubstitute($ptr, $substitute, $Type); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + return 1; + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 2: Multiple Substitution Subtable : 1 to n + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 2) { + // Flag = Ignore + if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) { + return 0; + } + $Coverage = $subtable_offset + $this->read_ushort(); + $GlyphPos = $LuCoverage[$currGID]; + $this->skip(2); + $this->skip($GlyphPos * 2); + $Sequences = $subtable_offset + $this->read_short(); + + $this->seek($Sequences); + $GlyphCount = $this->read_short(); + $SubstituteGlyphs = []; + for ($g = 0; $g < $GlyphCount; $g++) { + $sgid = $this->read_ushort(); + $SubstituteGlyphs[] = $this->glyphToChar($sgid); + } + + $shift = $this->GSUBsubstitute($ptr, $SubstituteGlyphs, $Type); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + return $shift; + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 3: Alternate Forms : 1 to 1(n) + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 3) { + // Flag = Ignore + if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) { + return 0; + } + $Coverage = $subtable_offset + $this->read_ushort(); + $AlternateSetCount = $this->read_short(); + ///////////////////////////////////////////////////////////////////////////////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // Need to set alternate IF set by CSS3 font-feature for a tag + // i.e. if this is 'salt' alternate may be set to 2 + // default value will be $alt=1 ( === index of 0 in list of alternates) + $alt = 1; // $alt=1 points to Alternative[0] + if ($tagInt > 1) { + $alt = $tagInt; + } + ///////////////////////////////////////////////////////////////////////////////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + if ($alt == 0) { + return 0; + } // If specified alternate not present, cancel [ or could default $alt = 1 ?] + + $GlyphPos = $LuCoverage[$currGID]; + $this->skip($GlyphPos * 2); + + $AlternateSets = $subtable_offset + $this->read_short(); + $this->seek($AlternateSets); + + $AlternateGlyphCount = $this->read_short(); + if ($alt > $AlternateGlyphCount) { + return 0; + } // If specified alternate not present, cancel [ or could default $alt = 1 ?] + + $this->skip(($alt - 1) * 2); + $GlyphID = $this->read_ushort(); + + $substitute = $this->glyphToChar($GlyphID); + $shift = $this->GSUBsubstitute($ptr, $substitute, $Type); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + return 1; + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 4: Ligature Substitution Subtable : n to 1 + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 4) { + // Flag = Ignore + if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) { + return 0; + } + $Coverage = $subtable_offset + $this->read_ushort(); + $FirstGlyphPos = $LuCoverage[$currGID]; + + $LigSetCount = $this->read_short(); + + $this->skip($FirstGlyphPos * 2); + $LigSet = $subtable_offset + $this->read_short(); + + $this->seek($LigSet); + $LigCount = $this->read_short(); + // LigatureSet i.e. all starting with the same first Glyph $currGlyph + $LigatureOffset = []; + for ($g = 0; $g < $LigCount; $g++) { + $LigatureOffset[$g] = $LigSet + $this->read_ushort(); + } + for ($g = 0; $g < $LigCount; $g++) { + // Ligature tables + $this->seek($LigatureOffset[$g]); + $LigGlyph = $this->read_ushort(); // Output Ligature GlyphID + $substitute = $this->glyphToChar($LigGlyph); + $CompCount = $this->read_ushort(); + + $spos = $ptr; + $match = true; + $GlyphPos = []; + $GlyphPos[] = $spos; + for ($l = 1; $l < $CompCount; $l++) { + $gid = $this->read_ushort(); + $checkGlyph = $this->glyphToChar($gid); // Other component/input Glyphs starting at position 2 (arrayindex 1) + + $spos++; + //while $this->OTLdata[$spos]['uni'] is an "ignore" => spos++ + while (isset($this->OTLdata[$spos]) && strpos($ignore, $this->OTLdata[$spos]['hex']) !== false) { + $spos++; + } + + if (isset($this->OTLdata[$spos]) && $this->OTLdata[$spos]['uni'] == $checkGlyph) { + $GlyphPos[] = $spos; + } else { + $match = false; + break; + } + } + + + if ($match) { + $shift = $this->GSUBsubstitute($ptr, $substitute, $Type, $GlyphPos); // GlyphPos contains positions to set null + if ($this->debugOTL && $shift) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + return ($spos - $ptr + 1 - ($CompCount - 1)); + } + } + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 5: Contextual Substitution Subtable + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 5) { + //=========== + // Format 1: Simple Context Glyph Substitution + //=========== + if ($SubstFormat == 1) { + $CoverageTableOffset = $subtable_offset + $this->read_ushort(); + $SubRuleSetCount = $this->read_ushort(); + $SubRuleSetOffset = []; + for ($b = 0; $b < $SubRuleSetCount; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $SubRuleSetOffset[] = $offset; + } else { + $SubRuleSetOffset[] = $subtable_offset + $offset; + } + } + + // SubRuleSet tables: All contexts beginning with the same glyph + // Select the SubRuleSet required using the position of the glyph in the coverage table + $GlyphPos = $LuCoverage[$currGID]; + if ($SubRuleSetOffset[$GlyphPos] > 0) { + $this->seek($SubRuleSetOffset[$GlyphPos]); + $SubRuleCnt = $this->read_ushort(); + $SubRule = []; + for ($b = 0; $b < $SubRuleCnt; $b++) { + $SubRule[$b] = $SubRuleSetOffset[$GlyphPos] + $this->read_ushort(); + } + for ($b = 0; $b < $SubRuleCnt; $b++) { // EACH RULE + $this->seek($SubRule[$b]); + $InputGlyphCount = $this->read_ushort(); + $SubstCount = $this->read_ushort(); + + $Backtrack = []; + $Lookahead = []; + $Input = []; + $Input[0] = $this->OTLdata[$ptr]['uni']; + for ($r = 1; $r < $InputGlyphCount; $r++) { + $gid = $this->read_ushort(); + $Input[$r] = $this->glyphToChar($gid); + } + $matched = $this->checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr); + if ($matched) { + if ($this->debugOTL) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + for ($p = 0; $p < $SubstCount; $p++) { // EACH LOOKUP + $SequenceIndex[$p] = $this->read_ushort(); + $LookupListIndex[$p] = $this->read_ushort(); + } + + for ($p = 0; $p < $SubstCount; $p++) { + // Apply $LookupListIndex at $SequenceIndex + if ($SequenceIndex[$p] >= $InputGlyphCount) { + continue; + } + $lu = $LookupListIndex[$p]; + $luType = $this->GSUBLookups[$lu]['Type']; + $luFlag = $this->GSUBLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SequenceIndex[$p]]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt); + if ($shift) { + break; + } + } + } + + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + } + return 0; + } //=========== + // Format 2: + //=========== + // Format 2: Class-based Context Glyph Substitution + elseif ($SubstFormat == 2) { + $CoverageTableOffset = $subtable_offset + $this->read_ushort(); + $InputClassDefOffset = $subtable_offset + $this->read_ushort(); + $SubClassSetCnt = $this->read_ushort(); + $SubClassSetOffset = []; + for ($b = 0; $b < $SubClassSetCnt; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $SubClassSetOffset[] = $offset; + } else { + $SubClassSetOffset[] = $subtable_offset + $offset; + } + } + + $InputClasses = $this->_getClasses($InputClassDefOffset); + + for ($s = 0; $s < $SubClassSetCnt; $s++) { // $SubClassSet is ordered by input class-may be NULL + // Select $SubClassSet if currGlyph is in First Input Class + if ($SubClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) { + $this->seek($SubClassSetOffset[$s]); + $SubClassRuleCnt = $this->read_ushort(); + $SubClassRule = []; + for ($b = 0; $b < $SubClassRuleCnt; $b++) { + $SubClassRule[$b] = $SubClassSetOffset[$s] + $this->read_ushort(); + } + + for ($b = 0; $b < $SubClassRuleCnt; $b++) { // EACH RULE + $this->seek($SubClassRule[$b]); + $InputGlyphCount = $this->read_ushort(); + $SubstCount = $this->read_ushort(); + $Input = []; + for ($r = 1; $r < $InputGlyphCount; $r++) { + $Input[$r] = $this->read_ushort(); + } + + $inputClass = $s; + + $inputGlyphs = []; + $inputGlyphs[0] = $InputClasses[$inputClass]; + + if ($InputGlyphCount > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) { + $classindex = $Input[$gcl]; + if (isset($InputClasses[$classindex])) { + $inputGlyphs[$gcl] = $InputClasses[$classindex]; + } else { + $inputGlyphs[$gcl] = ''; + } + } + } + + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = []; + for ($gc = 1; $gc <= count($InputClasses); $gc++) { + if (is_array($InputClasses[$gc])) { + $class0excl = $class0excl + $InputClasses[$gc]; + } + } + + $backtrackGlyphs = []; + $lookaheadGlyphs = []; + + $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl); + if ($matched) { + if ($this->debugOTL) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + for ($p = 0; $p < $SubstCount; $p++) { // EACH LOOKUP + $SequenceIndex[$p] = $this->read_ushort(); + $LookupListIndex[$p] = $this->read_ushort(); + } + + for ($p = 0; $p < $SubstCount; $p++) { + // Apply $LookupListIndex at $SequenceIndex + if ($SequenceIndex[$p] >= $InputGlyphCount) { + continue; + } + $lu = $LookupListIndex[$p]; + $luType = $this->GSUBLookups[$lu]['Type']; + $luFlag = $this->GSUBLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SequenceIndex[$p]]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt); + if ($shift) { + break; + } + } + } + + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + } + } + + return 0; + } //=========== + // Format 3: + //=========== + // Format 3: Coverage-based Context Glyph Substitution + elseif ($SubstFormat == 3) { + throw new \Mpdf\MpdfException("GSUB Lookup Type " . $Type . " Format " . $SubstFormat . " not TESTED YET."); + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 6: Chaining Contextual Substitution Subtable + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 6) { + //=========== + // Format 1: + //=========== + // Format 1: Simple Chaining Context Glyph Substitution + if ($SubstFormat == 1) { + $Coverage = $subtable_offset + $this->read_ushort(); + $GlyphPos = $LuCoverage[$currGID]; + $ChainSubRuleSetCount = $this->read_ushort(); + // All of the ChainSubRule tables defining contexts that begin with the same first glyph are grouped together and defined in a ChainSubRuleSet table + $this->skip($GlyphPos * 2); + $ChainSubRuleSet = $subtable_offset + $this->read_ushort(); + $this->seek($ChainSubRuleSet); + $ChainSubRuleCount = $this->read_ushort(); + + for ($s = 0; $s < $ChainSubRuleCount; $s++) { + $ChainSubRule[$s] = $ChainSubRuleSet + $this->read_ushort(); + } + + for ($s = 0; $s < $ChainSubRuleCount; $s++) { + $this->seek($ChainSubRule[$s]); + + $BacktrackGlyphCount = $this->read_ushort(); + $Backtrack = []; + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $gid = $this->read_ushort(); + $Backtrack[] = $this->glyphToChar($gid); + } + $Input = []; + $Input[0] = $this->OTLdata[$ptr]['uni']; + $InputGlyphCount = $this->read_ushort(); + for ($b = 1; $b < $InputGlyphCount; $b++) { + $gid = $this->read_ushort(); + $Input[$b] = $this->glyphToChar($gid); + } + $LookaheadGlyphCount = $this->read_ushort(); + $Lookahead = []; + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $gid = $this->read_ushort(); + $Lookahead[] = $this->glyphToChar($gid); + } + + $matched = $this->checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr); + if ($matched) { + if ($this->debugOTL) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + $SubstCount = $this->read_ushort(); + for ($p = 0; $p < $SubstCount; $p++) { + // SubstLookupRecord + $SubstLookupRecord[$p]['SequenceIndex'] = $this->read_ushort(); + $SubstLookupRecord[$p]['LookupListIndex'] = $this->read_ushort(); + } + for ($p = 0; $p < $SubstCount; $p++) { + // Apply $SubstLookupRecord[$p]['LookupListIndex'] at $SubstLookupRecord[$p]['SequenceIndex'] + if ($SubstLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) { + continue; + } + $lu = $SubstLookupRecord[$p]['LookupListIndex']; + $luType = $this->GSUBLookups[$lu]['Type']; + $luFlag = $this->GSUBLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SubstLookupRecord[$p]['SequenceIndex']]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt); + if ($shift) { + break; + } + } + } + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + return 0; + } //=========== + // Format 2: + //=========== + // Format 2: Class-based Chaining Context Glyph Substitution p257 + elseif ($SubstFormat == 2) { + // NB Format 2 specifies fixed class assignments (identical for each position in the backtrack, input, or lookahead sequence) and exclusive classes (a glyph cannot be in more than one class at a time) + + $CoverageTableOffset = $subtable_offset + $this->read_ushort(); + $BacktrackClassDefOffset = $subtable_offset + $this->read_ushort(); + $InputClassDefOffset = $subtable_offset + $this->read_ushort(); + $LookaheadClassDefOffset = $subtable_offset + $this->read_ushort(); + $ChainSubClassSetCnt = $this->read_ushort(); + $ChainSubClassSetOffset = []; + for ($b = 0; $b < $ChainSubClassSetCnt; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $ChainSubClassSetOffset[] = $offset; + } else { + $ChainSubClassSetOffset[] = $subtable_offset + $offset; + } + } + + $BacktrackClasses = $this->_getClasses($BacktrackClassDefOffset); + $InputClasses = $this->_getClasses($InputClassDefOffset); + $LookaheadClasses = $this->_getClasses($LookaheadClassDefOffset); + + for ($s = 0; $s < $ChainSubClassSetCnt; $s++) { // $ChainSubClassSet is ordered by input class-may be NULL + // Select $ChainSubClassSet if currGlyph is in First Input Class + if ($ChainSubClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) { + $this->seek($ChainSubClassSetOffset[$s]); + $ChainSubClassRuleCnt = $this->read_ushort(); + $ChainSubClassRule = []; + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { + $ChainSubClassRule[$b] = $ChainSubClassSetOffset[$s] + $this->read_ushort(); + } + + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { // EACH RULE + $this->seek($ChainSubClassRule[$b]); + $BacktrackGlyphCount = $this->read_ushort(); + for ($r = 0; $r < $BacktrackGlyphCount; $r++) { + $Backtrack[$r] = $this->read_ushort(); + } + $InputGlyphCount = $this->read_ushort(); + for ($r = 1; $r < $InputGlyphCount; $r++) { + $Input[$r] = $this->read_ushort(); + } + $LookaheadGlyphCount = $this->read_ushort(); + for ($r = 0; $r < $LookaheadGlyphCount; $r++) { + $Lookahead[$r] = $this->read_ushort(); + } + + + // These contain classes of glyphs as arrays + // $InputClasses[(class)] e.g. 0x02E6,0x02E7,0x02E8 + // $LookaheadClasses[(class)] + // $BacktrackClasses[(class)] + // These contain arrays of classIndexes + // [Backtrack] [Lookahead] and [Input] (Input is from the second position only) + + + $inputClass = $s; //??? + + $inputGlyphs = []; + $inputGlyphs[0] = $InputClasses[$inputClass]; + + if ($InputGlyphCount > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) { + $classindex = $Input[$gcl]; + if (isset($InputClasses[$classindex])) { + $inputGlyphs[$gcl] = $InputClasses[$classindex]; + } else { + $inputGlyphs[$gcl] = ''; + } + } + } + + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = []; + for ($gc = 1; $gc <= count($InputClasses); $gc++) { + if (isset($InputClasses[$gc])) { + $class0excl = $class0excl + $InputClasses[$gc]; + } + } + + if ($BacktrackGlyphCount) { + for ($gcl = 0; $gcl < $BacktrackGlyphCount; $gcl++) { + $classindex = $Backtrack[$gcl]; + if (isset($BacktrackClasses[$classindex])) { + $backtrackGlyphs[$gcl] = $BacktrackClasses[$classindex]; + } else { + $backtrackGlyphs[$gcl] = ''; + } + } + } else { + $backtrackGlyphs = []; + } + + // Class 0 contains all the glyphs NOT in the other classes + $bclass0excl = []; + for ($gc = 1; $gc <= count($BacktrackClasses); $gc++) { + if (isset($BacktrackClasses[$gc])) { + $bclass0excl = $bclass0excl + $BacktrackClasses[$gc]; + } + } + + + if ($LookaheadGlyphCount) { + for ($gcl = 0; $gcl < $LookaheadGlyphCount; $gcl++) { + $classindex = $Lookahead[$gcl]; + if (isset($LookaheadClasses[$classindex])) { + $lookaheadGlyphs[$gcl] = $LookaheadClasses[$classindex]; + } else { + $lookaheadGlyphs[$gcl] = ''; + } + } + } else { + $lookaheadGlyphs = []; + } + + // Class 0 contains all the glyphs NOT in the other classes + $lclass0excl = []; + for ($gc = 1; $gc <= count($LookaheadClasses); $gc++) { + if (isset($LookaheadClasses[$gc])) { + $lclass0excl = $lclass0excl + $LookaheadClasses[$gc]; + } + } + + + $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl, $bclass0excl, $lclass0excl); + if ($matched) { + if ($this->debugOTL) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + $SubstCount = $this->read_ushort(); + for ($p = 0; $p < $SubstCount; $p++) { // EACH LOOKUP + $SequenceIndex[$p] = $this->read_ushort(); + $LookupListIndex[$p] = $this->read_ushort(); + } + + for ($p = 0; $p < $SubstCount; $p++) { + // Apply $LookupListIndex at $SequenceIndex + if ($SequenceIndex[$p] >= $InputGlyphCount) { + continue; + } + $lu = $LookupListIndex[$p]; + $luType = $this->GSUBLookups[$lu]['Type']; + $luFlag = $this->GSUBLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SequenceIndex[$p]]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt); + if ($shift) { + break; + } + } + } + + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + } + } + + return 0; + } //=========== + // Format 3: + //=========== + // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + elseif ($SubstFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $InputGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $InputGlyphCount; $b++) { + $CoverageInputOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $LookaheadGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $SubstCount = $this->read_ushort(); + $save_pos = $this->_pos; // Save the point just after PosCount + + $CoverageBacktrackGlyphs = []; + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $this->seek($CoverageBacktrackOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageBacktrackGlyphs[$b] = implode("|", $glyphs); + } + $CoverageInputGlyphs = []; + for ($b = 0; $b < $InputGlyphCount; $b++) { + $this->seek($CoverageInputOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageInputGlyphs[$b] = implode("|", $glyphs); + } + $CoverageLookaheadGlyphs = []; + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $this->seek($CoverageLookaheadOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageLookaheadGlyphs[$b] = implode("|", $glyphs); + } + + $matched = $this->checkContextMatchMultiple($CoverageInputGlyphs, $CoverageBacktrackGlyphs, $CoverageLookaheadGlyphs, $ignore, $ptr); + if ($matched) { + if ($this->debugOTL) { + $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level); + } + + $this->seek($save_pos); // Return to just after PosCount + for ($p = 0; $p < $SubstCount; $p++) { + // SubstLookupRecord + $SubstLookupRecord[$p]['SequenceIndex'] = $this->read_ushort(); + $SubstLookupRecord[$p]['LookupListIndex'] = $this->read_ushort(); + } + for ($p = 0; $p < $SubstCount; $p++) { + // Apply $SubstLookupRecord[$p]['LookupListIndex'] at $SubstLookupRecord[$p]['SequenceIndex'] + if ($SubstLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) { + continue; + } + $lu = $SubstLookupRecord[$p]['LookupListIndex']; + $luType = $this->GSUBLookups[$lu]['Type']; + $luFlag = $this->GSUBLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SubstLookupRecord[$p]['SequenceIndex']]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GSUBLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt); + if ($shift) { + break; + } + } + } + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return (isset($shift) ? $shift : 0); + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + + return 0; + } + } else { + throw new \Mpdf\MpdfException("GSUB Lookup Type " . $Type . " not supported."); + } + } + + function _updateLigatureMarks($pos, $n) + { + if ($n > 0) { + // Update position of Ligatures and associated Marks + // Foreach lig/assocMarks + // Any position lpos or mpos > $pos + count($substitute) + // $this->assocMarks = array(); // assocMarks[$pos mpos] => array(compID, ligPos) + // $this->assocLigs = array(); // Ligatures[$pos lpos] => nc + for ($p = count($this->OTLdata) - 1; $p >= ($pos + $n); $p--) { + if (isset($this->assocLigs[$p])) { + $tmp = $this->assocLigs[$p]; + unset($this->assocLigs[$p]); + $this->assocLigs[($p + $n)] = $tmp; + } + } + for ($p = count($this->OTLdata) - 1; $p >= 0; $p--) { + if (isset($this->assocMarks[$p])) { + if ($this->assocMarks[$p]['ligPos'] >= ($pos + $n)) { + $this->assocMarks[$p]['ligPos'] += $n; + } + if ($p >= ($pos + $n)) { + $tmp = $this->assocMarks[$p]; + unset($this->assocMarks[$p]); + $this->assocMarks[($p + $n)] = $tmp; + } + } + } + } elseif ($n < 1) { // glyphs removed + $nrem = -$n; + // Update position of pre-existing Ligatures and associated Marks + for ($p = ($pos + 1); $p < count($this->OTLdata); $p++) { + if (isset($this->assocLigs[$p])) { + $tmp = $this->assocLigs[$p]; + unset($this->assocLigs[$p]); + $this->assocLigs[($p - $nrem)] = $tmp; + } + } + for ($p = 0; $p < count($this->OTLdata); $p++) { + if (isset($this->assocMarks[$p])) { + if ($this->assocMarks[$p]['ligPos'] >= ($pos)) { + $this->assocMarks[$p]['ligPos'] -= $nrem; + } + if ($p > $pos) { + $tmp = $this->assocMarks[$p]; + unset($this->assocMarks[$p]); + $this->assocMarks[($p - $nrem)] = $tmp; + } + } + } + } + } + + function GSUBsubstitute($pos, $substitute, $Type, $GlyphPos = null) + { + + // LookupType 1: Simple Substitution Subtable : 1 to 1 + // LookupType 3: Alternate Forms : 1 to 1(n) + if ($Type == 1 || $Type == 3) { + $this->OTLdata[$pos]['uni'] = $substitute; + $this->OTLdata[$pos]['hex'] = $this->unicode_hex($substitute); + return 1; + } // LookupType 2: Multiple Substitution Subtable : 1 to n + elseif ($Type == 2) { + for ($i = 0; $i < count($substitute); $i++) { + $uni = $substitute[$i]; + $newOTLdata[$i] = []; + $newOTLdata[$i]['uni'] = $uni; + $newOTLdata[$i]['hex'] = $this->unicode_hex($uni); + + + // Get types of new inserted chars - or replicate type of char being replaced + // $bt = Ucdn::get_bidi_class($uni); + // if (!$bt) { + $bt = $this->OTLdata[$pos]['bidi_type']; + // } + + if (strpos($this->GlyphClassMarks, $newOTLdata[$i]['hex']) !== false) { + $gp = 'M'; + } elseif ($uni == 32) { + $gp = 'S'; + } else { + $gp = 'C'; + } + + // Need to update matra_type ??? of new glyphs inserted ??????????????????????????????????????? + + $newOTLdata[$i]['bidi_type'] = $bt; + $newOTLdata[$i]['group'] = $gp; + + // Need to update details of new glyphs inserted + $newOTLdata[$i]['general_category'] = $this->OTLdata[$pos]['general_category']; + + if ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') { + $newOTLdata[$i]['indic_category'] = $this->OTLdata[$pos]['indic_category']; + $newOTLdata[$i]['indic_position'] = $this->OTLdata[$pos]['indic_position']; + } elseif ($this->shaper == 'M') { + $newOTLdata[$i]['myanmar_category'] = $this->OTLdata[$pos]['myanmar_category']; + $newOTLdata[$i]['myanmar_position'] = $this->OTLdata[$pos]['myanmar_position']; + } + if (isset($this->OTLdata[$pos]['mask'])) { + $newOTLdata[$i]['mask'] = $this->OTLdata[$pos]['mask']; + } + if (isset($this->OTLdata[$pos]['syllable'])) { + $newOTLdata[$i]['syllable'] = $this->OTLdata[$pos]['syllable']; + } + } + if ($this->shaper == 'K' || $this->shaper == 'T' || $this->shaper == 'L') { + if ($this->OTLdata[$pos]['wordend']) { + $newOTLdata[count($substitute) - 1]['wordend'] = true; + } + } + + array_splice($this->OTLdata, $pos, 1, $newOTLdata); // Replace 1 with n + // Update position of Ligatures and associated Marks + // count($substitute)-1 is the number of glyphs added + $nadd = count($substitute) - 1; + $this->_updateLigatureMarks($pos, $nadd); + return count($substitute); + } // LookupType 4: Ligature Substitution Subtable : n to 1 + elseif ($Type == 4) { + // Create Ligatures and associated Marks + $firstGlyph = $this->OTLdata[$pos]['hex']; + + // If all components of the ligature are marks (and in the same syllable), we call this a mark ligature. + $contains_marks = false; + $contains_nonmarks = false; + if (isset($this->OTLdata[$pos]['syllable'])) { + $current_syllable = $this->OTLdata[$pos]['syllable']; + } else { + $current_syllable = 0; + } + for ($i = 0; $i < count($GlyphPos); $i++) { + // If subsequent components are not Marks as well - don't ligate + $unistr = $this->OTLdata[$GlyphPos[$i]]['hex']; + if ($this->restrictToSyllable && isset($this->OTLdata[$GlyphPos[$i]]['syllable']) && $this->OTLdata[$GlyphPos[$i]]['syllable'] != $current_syllable) { + return 0; + } + if (strpos($this->GlyphClassMarks, $unistr) !== false) { + $contains_marks = true; + } else { + $contains_nonmarks = true; + } + } + if ($contains_marks && !$contains_nonmarks) { + // Mark Ligature (all components are Marks) + $firstMarkAssoc = ''; + if (isset($this->assocMarks[$pos])) { + $firstMarkAssoc = $this->assocMarks[$pos]; + } + // If all components of the ligature are marks, we call this a mark ligature. + for ($i = 1; $i < count($GlyphPos); $i++) { + // If subsequent components are not Marks as well - don't ligate + // $unistr = $this->OTLdata[$GlyphPos[$i]]['hex']; + // if (strpos($this->GlyphClassMarks, $unistr )===false) { return; } + + $nextMarkAssoc = ''; + if (isset($this->assocMarks[$GlyphPos[$i]])) { + $nextMarkAssoc = $this->assocMarks[$GlyphPos[$i]]; + } + // If first component was attached to a previous ligature component, + // all subsequent components should be attached to the same ligature + // component, otherwise we shouldn't ligate them. + // If first component was NOT attached to a previous ligature component, + // all subsequent components should also NOT be attached to any ligature component, + if ($firstMarkAssoc != $nextMarkAssoc) { + // unless they are attached to the first component itself! + // if (!is_array($nextMarkAssoc) || $nextMarkAssoc['ligPos']!= $pos) { return; } + // Update/Edit - In test with myanmartext font + // င်္က္ကျြွေိ + // => Lookup 17 E003 E066B E05A 102D + // E003 and 102D should form a mark ligature, but 102D is already associated with (non-mark) ligature E05A + // So instead of disallowing the mark ligature to form, just dissociate... + if (!is_array($nextMarkAssoc) || $nextMarkAssoc['ligPos'] != $pos) { + unset($this->assocMarks[$GlyphPos[$i]]); + } + } + } + + /* + * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave + * the ligature to keep its old ligature id. This will allow it to attach to + * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH, + * and LAM,LAM,HEH form a ligature, they will leave SHADDA and FATHA wit a + * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature + * later, we don't want them to lose their ligature id/component, otherwise + * GPOS will fail to correctly position the mark ligature on top of the + * LAM,LAM,HEH ligature. + */ + // So if is_array($firstMarkAssoc) - the new (Mark) ligature should keep this association + + $lastPos = $GlyphPos[(count($GlyphPos) - 1)]; + } else { + /* + * - Ligatures cannot be formed across glyphs attached to different components + * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and + * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. + * However, it would be wrong to ligate that SHADDA,FATHA sequence. + * There is an exception to this: If a ligature tries ligating with marks that + * belong to it itself, go ahead, assuming that the font designer knows what + * they are doing (otherwise it can break Indic stuff when a matra wants to + * ligate with a conjunct...) + */ + + /* + * - If a ligature is formed of components that some of which are also ligatures + * themselves, and those ligature components had marks attached to *their* + * components, we have to attach the marks to the new ligature component + * positions! Now *that*'s tricky! And these marks may be following the + * last component of the whole sequence, so we should loop forward looking + * for them and update them. + * + * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a + * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature + * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature + * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to + * the new ligature with a component value of 2. + * + * This in fact happened to a font... See: + * https://bugzilla.gnome.org/show_bug.cgi?id=437633 + */ + + $currComp = 0; + for ($i = 0; $i < count($GlyphPos); $i++) { + if ($i > 0 && isset($this->assocLigs[$GlyphPos[$i]])) { // One of the other components is already a ligature + $nc = $this->assocLigs[$GlyphPos[$i]]; + } else { + $nc = 1; + } + // While next char to right is a mark (but not the next matched glyph) + // ?? + also include a Mark Ligature here + $ic = 1; + while ((($i == count($GlyphPos) - 1) || (isset($GlyphPos[$i + 1]) && ($GlyphPos[$i] + $ic) < $GlyphPos[$i + 1])) && isset($this->OTLdata[($GlyphPos[$i] + $ic)]) && strpos($this->GlyphClassMarks, $this->OTLdata[($GlyphPos[$i] + $ic)]['hex']) !== false) { + $newComp = $currComp; + if (isset($this->assocMarks[$GlyphPos[$i] + $ic])) { // One of the inbetween Marks is already associated with a Lig + // OK as long as it is associated with the current Lig + // if ($this->assocMarks[($GlyphPos[$i]+$ic)]['ligPos'] != ($GlyphPos[$i]+$ic)) { die("Problem #1"); } + $newComp += $this->assocMarks[($GlyphPos[$i] + $ic)]['compID']; + } + $this->assocMarks[($GlyphPos[$i] + $ic)] = ['compID' => $newComp, 'ligPos' => $pos]; + $ic++; + } + $currComp += $nc; + } + $lastPos = $GlyphPos[(count($GlyphPos) - 1)] + $ic - 1; + $this->assocLigs[$pos] = $currComp; // Number of components in new Ligature + } + + // Now remove the unwanted glyphs and associated metadata + $newOTLdata[0] = []; + + // Get types of new inserted chars - or replicate type of char being replaced + // $bt = Ucdn::get_bidi_class($substitute); + // if (!$bt) { + $bt = $this->OTLdata[$pos]['bidi_type']; + // } + + if (strpos($this->GlyphClassMarks, $this->unicode_hex($substitute)) !== false) { + $gp = 'M'; + } elseif ($substitute == 32) { + $gp = 'S'; + } else { + $gp = 'C'; + } + + // Need to update details of new glyphs inserted + $newOTLdata[0]['general_category'] = $this->OTLdata[$pos]['general_category']; + + $newOTLdata[0]['bidi_type'] = $bt; + $newOTLdata[0]['group'] = $gp; + + // KASHIDA: If forming a ligature when the last component was identified as a kashida point (final form) + // If previous/first component of ligature is a medial form, then keep this as a kashida point + // TEST (Arabic Typesetting) يَنتُم + $ka = 0; + if (isset($this->OTLdata[$GlyphPos[(count($GlyphPos) - 1)]]['GPOSinfo']['kashida'])) { + $ka = $this->OTLdata[$GlyphPos[(count($GlyphPos) - 1)]]['GPOSinfo']['kashida']; + } + if ($ka == 1 && isset($this->OTLdata[$pos]['form']) && $this->OTLdata[$pos]['form'] == 3) { + $newOTLdata[0]['GPOSinfo']['kashida'] = $ka; + } + + $newOTLdata[0]['uni'] = $substitute; + $newOTLdata[0]['hex'] = $this->unicode_hex($substitute); + + if ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') { + $newOTLdata[0]['indic_category'] = $this->OTLdata[$pos]['indic_category']; + $newOTLdata[0]['indic_position'] = $this->OTLdata[$pos]['indic_position']; + } elseif ($this->shaper == 'M') { + $newOTLdata[0]['myanmar_category'] = $this->OTLdata[$pos]['myanmar_category']; + $newOTLdata[0]['myanmar_position'] = $this->OTLdata[$pos]['myanmar_position']; + } + if (isset($this->OTLdata[$pos]['mask'])) { + $newOTLdata[0]['mask'] = $this->OTLdata[$pos]['mask']; + } + if (isset($this->OTLdata[$pos]['syllable'])) { + $newOTLdata[0]['syllable'] = $this->OTLdata[$pos]['syllable']; + } + + $newOTLdata[0]['is_ligature'] = true; + + + array_splice($this->OTLdata, $pos, 1, $newOTLdata); + + // GlyphPos contains array of arr_pos to set null - not necessarily contiguous + // +- Remove any assocMarks or assocLigs from the main components (the ones that are deleted) + for ($i = count($GlyphPos) - 1; $i > 0; $i--) { + $gpos = $GlyphPos[$i]; + array_splice($this->OTLdata, $gpos, 1); + unset($this->assocLigs[$gpos]); + unset($this->assocMarks[$gpos]); + } + // $this->assocLigs = array(); // Ligatures[$posarr lpos] => nc + // $this->assocMarks = array(); // assocMarks[$posarr mpos] => array(compID, ligPos) + // Update position of pre-existing Ligatures and associated Marks + // Start after first GlyphPos + // count($GlyphPos)-1 is the number of glyphs removed from string + for ($p = ($GlyphPos[0] + 1); $p < (count($this->OTLdata) + count($GlyphPos) - 1); $p++) { + $nrem = 0; // Number of Glyphs removed at this point in the string + for ($i = 0; $i < count($GlyphPos); $i++) { + if ($i > 0 && $p > $GlyphPos[$i]) { + $nrem++; + } + } + if (isset($this->assocLigs[$p])) { + $tmp = $this->assocLigs[$p]; + unset($this->assocLigs[$p]); + $this->assocLigs[($p - $nrem)] = $tmp; + } + if (isset($this->assocMarks[$p])) { + $tmp = $this->assocMarks[$p]; + unset($this->assocMarks[$p]); + if ($tmp['ligPos'] > $GlyphPos[0]) { + $tmp['ligPos'] -= $nrem; + } + $this->assocMarks[($p - $nrem)] = $tmp; + } + } + return 1; + } else { + return 0; + } + } + + //////////////////////////////////////////////////////////////// + ////////// ARABIC ///////////////////////////////// + //////////////////////////////////////////////////////////////// + private function arabic_initialise() + { + // cf. http://unicode.org/Public/UNIDATA/ArabicShaping.txt + // http://unicode.org/Public/UNIDATA/extracted/DerivedJoiningType.txt + // JOIN TO FOLLOWING LETTER IN LOGICAL ORDER (i.e. AS INITIAL/MEDIAL FORM) = Unicode Left-Joining (+ Dual-Joining + Join_Causing 00640) + $this->arabLeftJoining = [ + 0x0620 => 1, 0x0626 => 1, 0x0628 => 1, 0x062A => 1, 0x062B => 1, 0x062C => 1, 0x062D => 1, 0x062E => 1, + 0x0633 => 1, 0x0634 => 1, 0x0635 => 1, 0x0636 => 1, 0x0637 => 1, 0x0638 => 1, 0x0639 => 1, 0x063A => 1, + 0x063B => 1, 0x063C => 1, 0x063D => 1, 0x063E => 1, 0x063F => 1, 0x0640 => 1, 0x0641 => 1, 0x0642 => 1, + 0x0643 => 1, 0x0644 => 1, 0x0645 => 1, 0x0646 => 1, 0x0647 => 1, 0x0649 => 1, 0x064A => 1, 0x066E => 1, + 0x066F => 1, 0x0678 => 1, 0x0679 => 1, 0x067A => 1, 0x067B => 1, 0x067C => 1, 0x067D => 1, 0x067E => 1, + 0x067F => 1, 0x0680 => 1, 0x0681 => 1, 0x0682 => 1, 0x0683 => 1, 0x0684 => 1, 0x0685 => 1, 0x0686 => 1, + 0x0687 => 1, 0x069A => 1, 0x069B => 1, 0x069C => 1, 0x069D => 1, 0x069E => 1, 0x069F => 1, 0x06A0 => 1, + 0x06A1 => 1, 0x06A2 => 1, 0x06A3 => 1, 0x06A4 => 1, 0x06A5 => 1, 0x06A6 => 1, 0x06A7 => 1, 0x06A8 => 1, + 0x06A9 => 1, 0x06AA => 1, 0x06AB => 1, 0x06AC => 1, 0x06AD => 1, 0x06AE => 1, 0x06AF => 1, 0x06B0 => 1, + 0x06B1 => 1, 0x06B2 => 1, 0x06B3 => 1, 0x06B4 => 1, 0x06B5 => 1, 0x06B6 => 1, 0x06B7 => 1, 0x06B8 => 1, + 0x06B9 => 1, 0x06BA => 1, 0x06BB => 1, 0x06BC => 1, 0x06BD => 1, 0x06BE => 1, 0x06BF => 1, 0x06C1 => 1, + 0x06C2 => 1, 0x06CC => 1, 0x06CE => 1, 0x06D0 => 1, 0x06D1 => 1, 0x06FA => 1, 0x06FB => 1, 0x06FC => 1, + 0x06FF => 1, + /* Arabic Supplement */ + 0x0750 => 1, 0x0751 => 1, 0x0752 => 1, 0x0753 => 1, 0x0754 => 1, 0x0755 => 1, 0x0756 => 1, 0x0757 => 1, + 0x0758 => 1, 0x075C => 1, 0x075D => 1, 0x075E => 1, 0x075F => 1, 0x0760 => 1, 0x0761 => 1, 0x0762 => 1, + 0x0763 => 1, 0x0764 => 1, 0x0765 => 1, 0x0766 => 1, 0x0767 => 1, 0x0768 => 1, 0x0769 => 1, 0x076A => 1, + 0x076D => 1, 0x076E => 1, 0x076F => 1, 0x0770 => 1, 0x0772 => 1, 0x0775 => 1, 0x0776 => 1, 0x0777 => 1, + 0x077A => 1, 0x077B => 1, 0x077C => 1, 0x077D => 1, 0x077E => 1, 0x077F => 1, + /* Extended Arabic */ + 0x08A0 => 1, 0x08A2 => 1, 0x08A3 => 1, 0x08A4 => 1, 0x08A5 => 1, 0x08A6 => 1, 0x08A7 => 1, 0x08A8 => 1, + 0x08A9 => 1, + /* 'syrc' Syriac */ + 0x0712 => 1, 0x0713 => 1, 0x0714 => 1, 0x071A => 1, 0x071B => 1, 0x071C => 1, 0x071D => 1, 0x071F => 1, + 0x0720 => 1, 0x0721 => 1, 0x0722 => 1, 0x0723 => 1, 0x0724 => 1, 0x0725 => 1, 0x0726 => 1, 0x0727 => 1, + 0x0729 => 1, 0x072B => 1, 0x072D => 1, 0x072E => 1, 0x074E => 1, 0x074F => 1, + /* N'Ko */ + 0x07CA => 1, 0x07CB => 1, 0x07CC => 1, 0x07CD => 1, 0x07CE => 1, 0x07CF => 1, 0x07D0 => 1, 0x07D1 => 1, + 0x07D2 => 1, 0x07D3 => 1, 0x07D4 => 1, 0x07D5 => 1, 0x07D6 => 1, 0x07D7 => 1, 0x07D8 => 1, 0x07D9 => 1, + 0x07DA => 1, 0x07DB => 1, 0x07DC => 1, 0x07DD => 1, 0x07DE => 1, 0x07DF => 1, 0x07E0 => 1, 0x07E1 => 1, + 0x07E2 => 1, 0x07E3 => 1, 0x07E4 => 1, 0x07E5 => 1, 0x07E6 => 1, 0x07E7 => 1, 0x07E8 => 1, 0x07E9 => 1, + 0x07EA => 1, 0x07FA => 1, + /* Mandaic */ + 0x0841 => 1, 0x0842 => 1, 0x0843 => 1, 0x0844 => 1, 0x0845 => 1, 0x0847 => 1, 0x0848 => 1, 0x084A => 1, + 0x084B => 1, 0x084C => 1, 0x084D => 1, 0x084E => 1, 0x0850 => 1, 0x0851 => 1, 0x0852 => 1, 0x0853 => 1, + 0x0855 => 1, + /* ZWJ U+200D */ + 0x0200D => 1]; + + /* JOIN TO PREVIOUS LETTER IN LOGICAL ORDER (i.e. AS FINAL/MEDIAL FORM) = Unicode Right-Joining (+ Dual-Joining + Join_Causing) */ + $this->arabRightJoining = [ + 0x0620 => 1, 0x0622 => 1, 0x0623 => 1, 0x0624 => 1, 0x0625 => 1, 0x0626 => 1, 0x0627 => 1, 0x0628 => 1, + 0x0629 => 1, 0x062A => 1, 0x062B => 1, 0x062C => 1, 0x062D => 1, 0x062E => 1, 0x062F => 1, 0x0630 => 1, + 0x0631 => 1, 0x0632 => 1, 0x0633 => 1, 0x0634 => 1, 0x0635 => 1, 0x0636 => 1, 0x0637 => 1, 0x0638 => 1, + 0x0639 => 1, 0x063A => 1, 0x063B => 1, 0x063C => 1, 0x063D => 1, 0x063E => 1, 0x063F => 1, 0x0640 => 1, + 0x0641 => 1, 0x0642 => 1, 0x0643 => 1, 0x0644 => 1, 0x0645 => 1, 0x0646 => 1, 0x0647 => 1, 0x0648 => 1, + 0x0649 => 1, 0x064A => 1, 0x066E => 1, 0x066F => 1, 0x0671 => 1, 0x0672 => 1, 0x0673 => 1, 0x0675 => 1, + 0x0676 => 1, 0x0677 => 1, 0x0678 => 1, 0x0679 => 1, 0x067A => 1, 0x067B => 1, 0x067C => 1, 0x067D => 1, + 0x067E => 1, 0x067F => 1, 0x0680 => 1, 0x0681 => 1, 0x0682 => 1, 0x0683 => 1, 0x0684 => 1, 0x0685 => 1, + 0x0686 => 1, 0x0687 => 1, 0x0688 => 1, 0x0689 => 1, 0x068A => 1, 0x068B => 1, 0x068C => 1, 0x068D => 1, + 0x068E => 1, 0x068F => 1, 0x0690 => 1, 0x0691 => 1, 0x0692 => 1, 0x0693 => 1, 0x0694 => 1, 0x0695 => 1, + 0x0696 => 1, 0x0697 => 1, 0x0698 => 1, 0x0699 => 1, 0x069A => 1, 0x069B => 1, 0x069C => 1, 0x069D => 1, + 0x069E => 1, 0x069F => 1, 0x06A0 => 1, 0x06A1 => 1, 0x06A2 => 1, 0x06A3 => 1, 0x06A4 => 1, 0x06A5 => 1, + 0x06A6 => 1, 0x06A7 => 1, 0x06A8 => 1, 0x06A9 => 1, 0x06AA => 1, 0x06AB => 1, 0x06AC => 1, 0x06AD => 1, + 0x06AE => 1, 0x06AF => 1, 0x06B0 => 1, 0x06B1 => 1, 0x06B2 => 1, 0x06B3 => 1, 0x06B4 => 1, 0x06B5 => 1, + 0x06B6 => 1, 0x06B7 => 1, 0x06B8 => 1, 0x06B9 => 1, 0x06BA => 1, 0x06BB => 1, 0x06BC => 1, 0x06BD => 1, + 0x06BE => 1, 0x06BF => 1, 0x06C0 => 1, 0x06C1 => 1, 0x06C2 => 1, 0x06C3 => 1, 0x06C4 => 1, 0x06C5 => 1, + 0x06C6 => 1, 0x06C7 => 1, 0x06C8 => 1, 0x06C9 => 1, 0x06CA => 1, 0x06CB => 1, 0x06CC => 1, 0x06CD => 1, + 0x06CE => 1, 0x06CF => 1, 0x06D0 => 1, 0x06D1 => 1, 0x06D2 => 1, 0x06D3 => 1, 0x06D5 => 1, 0x06EE => 1, + 0x06EF => 1, 0x06FA => 1, 0x06FB => 1, 0x06FC => 1, 0x06FF => 1, + /* Arabic Supplement */ + 0x0750 => 1, 0x0751 => 1, 0x0752 => 1, 0x0753 => 1, 0x0754 => 1, 0x0755 => 1, 0x0756 => 1, 0x0757 => 1, + 0x0758 => 1, 0x0759 => 1, 0x075A => 1, 0x075B => 1, 0x075C => 1, 0x075D => 1, 0x075E => 1, 0x075F => 1, + 0x0760 => 1, 0x0761 => 1, 0x0762 => 1, 0x0763 => 1, 0x0764 => 1, 0x0765 => 1, 0x0766 => 1, 0x0767 => 1, + 0x0768 => 1, 0x0769 => 1, 0x076A => 1, 0x076B => 1, 0x076C => 1, 0x076D => 1, 0x076E => 1, 0x076F => 1, + 0x0770 => 1, 0x0771 => 1, 0x0772 => 1, 0x0773 => 1, 0x0774 => 1, 0x0775 => 1, 0x0776 => 1, 0x0777 => 1, + 0x0778 => 1, 0x0779 => 1, 0x077A => 1, 0x077B => 1, 0x077C => 1, 0x077D => 1, 0x077E => 1, 0x077F => 1, + /* Extended Arabic */ + 0x08A0 => 1, 0x08A2 => 1, 0x08A3 => 1, 0x08A4 => 1, 0x08A5 => 1, 0x08A6 => 1, 0x08A7 => 1, 0x08A8 => 1, + 0x08A9 => 1, 0x08AA => 1, 0x08AB => 1, 0x08AC => 1, + /* 'syrc' Syriac */ + 0x0710 => 1, 0x0712 => 1, 0x0713 => 1, 0x0714 => 1, 0x0715 => 1, 0x0716 => 1, 0x0717 => 1, 0x0718 => 1, + 0x0719 => 1, 0x071A => 1, 0x071B => 1, 0x071C => 1, 0x071D => 1, 0x071E => 1, 0x071F => 1, 0x0720 => 1, + 0x0721 => 1, 0x0722 => 1, 0x0723 => 1, 0x0724 => 1, 0x0725 => 1, 0x0726 => 1, 0x0727 => 1, 0x0728 => 1, + 0x0729 => 1, 0x072A => 1, 0x072B => 1, 0x072C => 1, 0x072D => 1, 0x072E => 1, 0x072F => 1, 0x074D => 1, + 0x074E => 1, 0x074F, + /* N'Ko */ + 0x07CA => 1, 0x07CB => 1, 0x07CC => 1, 0x07CD => 1, 0x07CE => 1, 0x07CF => 1, 0x07D0 => 1, 0x07D1 => 1, + 0x07D2 => 1, 0x07D3 => 1, 0x07D4 => 1, 0x07D5 => 1, 0x07D6 => 1, 0x07D7 => 1, 0x07D8 => 1, 0x07D9 => 1, + 0x07DA => 1, 0x07DB => 1, 0x07DC => 1, 0x07DD => 1, 0x07DE => 1, 0x07DF => 1, 0x07E0 => 1, 0x07E1 => 1, + 0x07E2 => 1, 0x07E3 => 1, 0x07E4 => 1, 0x07E5 => 1, 0x07E6 => 1, 0x07E7 => 1, 0x07E8 => 1, 0x07E9 => 1, + 0x07EA => 1, 0x07FA => 1, + /* Mandaic */ + 0x0841 => 1, 0x0842 => 1, 0x0843 => 1, 0x0844 => 1, 0x0845 => 1, 0x0847 => 1, 0x0848 => 1, 0x084A => 1, + 0x084B => 1, 0x084C => 1, 0x084D => 1, 0x084E => 1, 0x0850 => 1, 0x0851 => 1, 0x0852 => 1, 0x0853 => 1, + 0x0855 => 1, + 0x0840 => 1, 0x0846 => 1, 0x0849 => 1, 0x084F => 1, 0x0854 => 1, /* Right joining */ + /* ZWJ U+200D */ + 0x0200D => 1]; + + /* VOWELS = TRANSPARENT-JOINING = Unicode Transparent-Joining type (not just vowels) */ + $this->arabTransparent = [ + 0x0610 => 1, 0x0611 => 1, 0x0612 => 1, 0x0613 => 1, 0x0614 => 1, 0x0615 => 1, 0x0616 => 1, 0x0617 => 1, + 0x0618 => 1, 0x0619 => 1, 0x061A => 1, 0x064B => 1, 0x064C => 1, 0x064D => 1, 0x064E => 1, 0x064F => 1, + 0x0650 => 1, 0x0651 => 1, 0x0652 => 1, 0x0653 => 1, 0x0654 => 1, 0x0655 => 1, 0x0656 => 1, 0x0657 => 1, + 0x0658 => 1, 0x0659 => 1, 0x065A => 1, 0x065B => 1, 0x065C => 1, 0x065D => 1, 0x065E => 1, 0x065F => 1, + 0x0670 => 1, 0x06D6 => 1, 0x06D7 => 1, 0x06D8 => 1, 0x06D9 => 1, 0x06DA => 1, 0x06DB => 1, 0x06DC => 1, + 0x06DF => 1, 0x06E0 => 1, 0x06E1 => 1, 0x06E2 => 1, 0x06E3 => 1, 0x06E4 => 1, 0x06E7 => 1, 0x06E8 => 1, + 0x06EA => 1, 0x06EB => 1, 0x06EC => 1, 0x06ED => 1, + /* Extended Arabic */ + 0x08E4 => 1, 0x08E5 => 1, 0x08E6 => 1, 0x08E7 => 1, 0x08E8 => 1, 0x08E9 => 1, 0x08EA => 1, 0x08EB => 1, + 0x08EC => 1, 0x08ED => 1, 0x08EE => 1, 0x08EF => 1, 0x08F0 => 1, 0x08F1 => 1, 0x08F2 => 1, 0x08F3 => 1, + 0x08F4 => 1, 0x08F5 => 1, 0x08F6 => 1, 0x08F7 => 1, 0x08F8 => 1, 0x08F9 => 1, 0x08FA => 1, 0x08FB => 1, + 0x08FC => 1, 0x08FD => 1, 0x08FE => 1, + /* Arabic ligatures in presentation form (converted in 'ccmp' in e.g. Arial and Times ? need to add others in this range) */ + 0xFC5E => 1, 0xFC5F => 1, 0xFC60 => 1, 0xFC61 => 1, 0xFC62 => 1, + /* 'syrc' Syriac */ + 0x070F => 1, 0x0711 => 1, 0x0730 => 1, 0x0731 => 1, 0x0732 => 1, 0x0733 => 1, 0x0734 => 1, 0x0735 => 1, + 0x0736 => 1, 0x0737 => 1, 0x0738 => 1, 0x0739 => 1, 0x073A => 1, 0x073B => 1, 0x073C => 1, 0x073D => 1, + 0x073E => 1, 0x073F => 1, 0x0740 => 1, 0x0741 => 1, 0x0742 => 1, 0x0743 => 1, 0x0744 => 1, 0x0745 => 1, + 0x0746 => 1, 0x0747 => 1, 0x0748 => 1, 0x0749 => 1, 0x074A => 1, + /* N'Ko */ + 0x07EB => 1, 0x07EC => 1, 0x07ED => 1, 0x07EE => 1, 0x07EF => 1, 0x07F0 => 1, 0x07F1 => 1, 0x07F2 => 1, + 0x07F3 => 1, + /* Mandaic */ + 0x0859 => 1, 0x085A => 1, 0x085B => 1, + ]; + } + + private function arabic_shaper($usetags, $scriptTag) + { + $chars = []; + for ($i = 0; $i < count($this->OTLdata); $i++) { + $chars[] = $this->OTLdata[$i]['hex']; + } + + $crntChar = null; + $prevChar = null; + $nextChar = null; + $output = []; + $max = count($chars); + for ($i = $max - 1; $i >= 0; $i--) { + $crntChar = $chars[$i]; + if ($i > 0) { + $prevChar = hexdec($chars[$i - 1]); + } else { + $prevChar = null; + } + if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 2])) { + $prevChar = hexdec($chars[$i - 2]); + if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 3])) { + $prevChar = hexdec($chars[$i - 3]); + if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 4])) { + $prevChar = hexdec($chars[$i - 4]); + } + } + } + if ($crntChar && isset($this->arabTransparentJoin[hexdec($crntChar)])) { + // If next_char = RightJoining && prev_char = LeftJoining: + if (isset($chars[$i + 1]) && $chars[$i + 1] && isset($this->arabRightJoining[hexdec($chars[$i + 1])]) && $prevChar && isset($this->arabLeftJoining[$prevChar])) { + $output[] = $this->get_arab_glyphs($crntChar, 1, $chars, $i, $scriptTag, $usetags); // <final> form + } else { + $output[] = $this->get_arab_glyphs($crntChar, 0, $chars, $i, $scriptTag, $usetags); // <isolated> form + } + continue; + } + if (hexdec($crntChar) < 128) { + $output[] = [$crntChar, 0]; + $nextChar = $crntChar; + continue; + } + // 0=ISOLATED FORM :: 1=FINAL :: 2=INITIAL :: 3=MEDIAL + $form = 0; + if ($prevChar && isset($this->arabLeftJoining[$prevChar])) { + $form++; + } + if ($nextChar && isset($this->arabRightJoining[hexdec($nextChar)])) { + $form += 2; + } + $output[] = $this->get_arab_glyphs($crntChar, $form, $chars, $i, $scriptTag, $usetags); + $nextChar = $crntChar; + } + $ra = array_reverse($output); + for ($i = 0; $i < count($this->OTLdata); $i++) { + $this->OTLdata[$i]['uni'] = hexdec($ra[$i][0]); + $this->OTLdata[$i]['hex'] = $ra[$i][0]; + $this->OTLdata[$i]['form'] = $ra[$i][1]; // Actaul form substituted 0=ISOLATED FORM :: 1=FINAL :: 2=INITIAL :: 3=MEDIAL + } + } + + private function get_arab_glyphs($char, $type, &$chars, $i, $scriptTag, $usetags) + { + // Optional Feature settings // doesn't control Syriac at present + if (($type === 0 && strpos($usetags, 'isol') === false) || ($type === 1 && strpos($usetags, 'fina') === false) || ($type === 2 && strpos($usetags, 'init') === false) || ($type === 3 && strpos($usetags, 'medi') === false)) { + return [$char, 0]; + } + + // 0=ISOLATED FORM :: 1=FINAL :: 2=INITIAL :: 3=MEDIAL (:: 4=MED2 :: 5=FIN2 :: 6=FIN3) + $retk = -1; + // Alaph 00710 in Syriac + if ($scriptTag == 'syrc' && $char == '00710') { + // if there is a preceding (base?) character *** should search back to previous base - ignoring vowels and change $n + // set $n as the position of the last base; for now we'll just do this: + $n = $i - 1; + // if the preceding (base) character cannot be joined to + // not in $this->arabLeftJoining i.e. not a char which can join to the next one + if (isset($chars[$n]) && isset($this->arabLeftJoining[hexdec($chars[$n])])) { + // if in the middle of Syriac words + if (isset($chars[$i + 1]) && preg_match('/[\x{0700}-\x{0745}]/u', UtfString::code2utf(hexdec($chars[$n]))) && preg_match('/[\x{0700}-\x{0745}]/u', UtfString::code2utf(hexdec($chars[$i + 1]))) && isset($this->arabGlyphs[$char][4])) { + $retk = 4; + } // if at the end of Syriac words + elseif (!isset($chars[$i + 1]) || !preg_match('/[\x{0700}-\x{0745}]/u', UtfString::code2utf(hexdec($chars[$i + 1])))) { + // if preceding base character IS (00715|00716|0072A) + if (strpos('0715|0716|072A', $chars[$n]) !== false && isset($this->arabGlyphs[$char][6])) { + $retk = 6; + } // elseif preceding base character is NOT (00715|00716|0072A) + elseif (isset($this->arabGlyphs[$char][5])) { + $retk = 5; + } + } + } + if ($retk != -1) { + return [$this->arabGlyphs[$char][$retk], $retk]; + } else { + return [$char, 0]; + } + } + + if (($type > 0 || $type === 0) && isset($this->arabGlyphs[$char][$type])) { + $retk = $type; + } elseif ($type == 3 && isset($this->arabGlyphs[$char][1])) { // if <medial> not defined, but <final>, return <final> + $retk = 1; + } elseif ($type == 2 && isset($this->arabGlyphs[$char][0])) { // if <initial> not defined, but <isolated>, return <isolated> + $retk = 0; + } + if ($retk != -1) { + $match = true; + // If GSUB includes a Backtrack or Lookahead condition (e.g. font ArabicTypesetting) + if (isset($this->arabGlyphs[$char]['prel'][$retk]) && $this->arabGlyphs[$char]['prel'][$retk]) { + $ig = 1; + foreach ($this->arabGlyphs[$char]['prel'][$retk] as $k => $v) { // $k starts 0, 1... + if (!isset($chars[$i - $ig - $k])) { + $match = false; + } elseif (strpos($v, $chars[$i - $ig - $k]) === false) { + while (strpos($this->arabGlyphs[$char]['ignore'][$retk], $chars[$i - $ig - $k]) !== false) { // ignore + $ig++; + } + if (!isset($chars[$i - $ig - $k])) { + $match = false; + } elseif (strpos($v, $chars[$i - $ig - $k]) === false) { + $match = false; + } + } + } + } + if (isset($this->arabGlyphs[$char]['postl'][$retk]) && $this->arabGlyphs[$char]['postl'][$retk]) { + $ig = 1; + foreach ($this->arabGlyphs[$char]['postl'][$retk] as $k => $v) { // $k starts 0, 1... + if (!isset($chars[$i + $ig + $k])) { + $match = false; + } elseif (strpos($v, $chars[$i + $ig + $k]) === false) { + while (strpos($this->arabGlyphs[$char]['ignore'][$retk], $chars[$i + $ig + $k]) !== false) { // ignore + $ig++; + } + if (!isset($chars[$i + $ig + $k])) { + $match = false; + } elseif (strpos($v, $chars[$i + $ig + $k]) === false) { + $match = false; + } + } + } + } + if ($match) { + return [$this->arabGlyphs[$char][$retk], $retk]; + } else { + return [$char, 0]; + } + } else { + return [$char, 0]; + } + } + + //////////////////////////////////////////////////////////////// + ///////////////// LINE BREAKING /////////////////////// + //////////////////////////////////////////////////////////////// + ///////////// TIBETAN LINE BREAKING /////////////////// + //////////////////////////////////////////////////////////////// + // Sets $this->OTLdata[$i]['wordend']=true at possible end of word boundaries + private function tibetanLineBreaking() + { + for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) { + // Break opportunities at U+0F0B Tsheg or U=0F0D + if (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] == 0x0F0B || $this->OTLdata[$ptr]['uni'] == 0x0F0D)) { + if (isset($this->OTLdata[$ptr + 1]['uni']) && ($this->OTLdata[$ptr + 1]['uni'] == 0x0F0D || $this->OTLdata[$ptr + 1]['uni'] == 0xF0E)) { + continue; + } + // Set end of word marker in OTLdata at matchpos + $this->OTLdata[$ptr]['wordend'] = true; + } + } + } + + /** + * South East Asian Linebreaking (Thai, Khmer and Lao) using dictionary of words + * + * Sets $this->OTLdata[$i]['wordend']=true at possible end of word boundaries + */ + private function seaLineBreaking() + { + // Load Line-breaking dictionary + if (!isset($this->lbdicts[$this->shaper]) && file_exists(__DIR__ . '/../data/linebrdict' . $this->shaper . '.dat')) { + $this->lbdicts[$this->shaper] = file_get_contents(__DIR__ . '/../data/linebrdict' . $this->shaper . '.dat'); + } + + $dict = &$this->lbdicts[$this->shaper]; + + // Find all word boundaries and mark end of word $this->OTLdata[$i]['wordend']=true on last character + // If Thai, allow for possible suffixes (not in Lao or Khmer) + // repeater/ellision characters + // (0x0E2F); // Ellision character THAI_PAIYANNOI 0x0E2F UTF-8 0xE0 0xB8 0xAF + // (0x0E46); // Repeat character THAI_MAIYAMOK 0x0E46 UTF-8 0xE0 0xB9 0x86 + // (0x0EC6); // Repeat character LAO UTF-8 0xE0 0xBB 0x86 + + $rollover = []; + $ptr = 0; + + while ($ptr < count($this->OTLdata) - 3) { + if (count($rollover)) { + $matches = $rollover; + $rollover = []; + } else { + $matches = $this->checkwordmatch($dict, $ptr); + } + if (count($matches) == 1) { + $matchpos = $matches[0]; + // Check for repeaters - if so $matchpos++ + if (isset($this->OTLdata[$matchpos + 1]['uni']) && ($this->OTLdata[$matchpos + 1]['uni'] == 0x0E2F || $this->OTLdata[$matchpos + 1]['uni'] == 0x0E46 || $this->OTLdata[$matchpos + 1]['uni'] == 0x0EC6)) { + $matchpos++; + } + // Set end of word marker in OTLdata at matchpos + $this->OTLdata[$matchpos]['wordend'] = true; + $ptr = $matchpos + 1; + } elseif (empty($matches)) { + $ptr++; + // Move past any ASCII characters + while (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] >> 8) == 0) { + $ptr++; + } + } else { // Multiple matches + $secondmatch = false; + for ($m = count($matches) - 1; $m >= 0; $m--) { + //for ($m=0;$m<count($matches);$m++) { + $firstmatch = $matches[$m]; + $matches2 = $this->checkwordmatch($dict, $firstmatch + 1); + if (count($matches2)) { + // Set end of word marker in OTLdata at matchpos + $this->OTLdata[$firstmatch]['wordend'] = true; + $ptr = $firstmatch + 1; + $rollover = $matches2; + $secondmatch = true; + break; + } + } + if (!$secondmatch) { + // Set end of word marker in OTLdata at end of longest first match + $this->OTLdata[$matches[count($matches) - 1]]['wordend'] = true; + $ptr = $matches[count($matches) - 1] + 1; + // Move past any ASCII characters + while (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] >> 8) == 0) { + $ptr++; + } + } + } + } + } + + private function checkwordmatch(&$dict, $ptr) + { + /* + Node type: Split. + Divide at < 98 >= 98 + Offset for >= 98 == 79 (long 4-byte unsigned) + + Node type: Linear match. + Char = 97 + + Intermediate match + + Final match + */ + + $dictptr = 0; + $ok = true; + $matches = []; + while ($ok) { + $x = ord($dict[$dictptr]); + $c = $this->OTLdata[$ptr]['uni'] & 0xFF; + if ($x == static::_DICT_INTERMEDIATE_MATCH) { +//echo "DICT_INTERMEDIATE_MATCH: ".dechex($c).'<br />'; + // Do not match if next character in text is a Mark + if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) { + $matches[] = $ptr - 1; + } + $dictptr++; + } elseif ($x == static::_DICT_FINAL_MATCH) { +//echo "DICT_FINAL_MATCH: ".dechex($c).'<br />'; + // Do not match if next character in text is a Mark + if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) { + $matches[] = $ptr - 1; + } + return $matches; + } elseif ($x == static::_DICT_NODE_TYPE_LINEAR) { +//echo "DICT_NODE_TYPE_LINEAR: ".dechex($c).'<br />'; + $dictptr++; + $m = ord($dict[$dictptr]); + if ($c == $m) { + $ptr++; + if ($ptr > count($this->OTLdata) - 1) { + $next = ord($dict[$dictptr + 1]); + if ($next == static::_DICT_INTERMEDIATE_MATCH || $next == static::_DICT_FINAL_MATCH) { + // Do not match if next character in text is a Mark + if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) { + $matches[] = $ptr - 1; + } + } + return $matches; + } + $dictptr++; + continue; + } else { +//echo "DICT_NODE_TYPE_LINEAR NOT: ".dechex($c).'<br />'; + return $matches; + } + } elseif ($x == static::_DICT_NODE_TYPE_SPLIT) { +//echo "DICT_NODE_TYPE_SPLIT ON ".dechex($d).": ".dechex($c).'<br />'; + $dictptr++; + $d = ord($dict[$dictptr]); + if ($c < $d) { + $dictptr += 5; + } else { + $dictptr++; + // Unsigned long 32-bit offset + $offset = (ord($dict[$dictptr]) * 16777216) + (ord($dict[$dictptr + 1]) << 16) + (ord($dict[$dictptr + 2]) << 8) + ord($dict[$dictptr + 3]); + $dictptr = $offset; + } + } else { +//echo "PROBLEM: ".($x).'<br />'; + $ok = false; // Something has gone wrong + } + } + + return $matches; + } + + //////////////////////////////////////////////////////////////// + ////////// GPOS /////////////////////////////////////// + //////////////////////////////////////////////////////////////// + private function _applyGPOSrules($LookupList, $is_old_spec = false) + { + foreach ($LookupList as $lu => $tag) { + $Type = $this->GPOSLookups[$lu]['Type']; + $Flag = $this->GPOSLookups[$lu]['Flag']; + $MarkFilteringSet = ''; + if (isset($this->GPOSLookups[$lu]['MarkFilteringSet'])) { + $MarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet']; + } + $ptr = 0; + // Test each glyph sequentially + while ($ptr < (count($this->OTLdata))) { // whilst there is another glyph ..0064 + $currGlyph = $this->OTLdata[$ptr]['hex']; + $currGID = $this->OTLdata[$ptr]['uni']; + $shift = 1; + foreach ($this->GPOSLookups[$lu]['Subtables'] as $c => $subtable_offset) { + // NB Coverage only looks at glyphs for position 1 (esp. 7.3 and 8.3) + if (isset($this->LuCoverage[$lu][$c][$currGID])) { + // Get rules from font GPOS subtable + if (isset($this->OTLdata[$ptr]['bidi_type'])) { // No need to check bidi_type - just a check that it exists + $shift = $this->_applyGPOSsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GPOS_offset + $this->GSUB_length), $Type, $Flag, $MarkFilteringSet, $this->LuCoverage[$lu][$c], $tag, 0, $is_old_spec); + if ($shift) { + break; + } + } + } + } + if ($shift == 0) { + $shift = 1; + } + $ptr += $shift; + } + } + } + + ////////////////////////////////////////////////////////////////////////////////// + // GPOS Types + // Lookup Type 1: Single Adjustment Positioning Subtable Adjust position of a single glyph + // Lookup Type 2: Pair Adjustment Positioning Subtable Adjust position of a pair of glyphs + // Lookup Type 3: Cursive Attachment Positioning Subtable Attach cursive glyphs + // Lookup Type 4: MarkToBase Attachment Positioning Subtable Attach a combining mark to a base glyph + // Lookup Type 5: MarkToLigature Attachment Positioning Subtable Attach a combining mark to a ligature + // Lookup Type 6: MarkToMark Attachment Positioning Subtable Attach a combining mark to another mark + // Lookup Type 7: Contextual Positioning Subtables Position one or more glyphs in context + // Lookup Type 8: Chaining Contextual Positioning Subtable Position one or more glyphs in chained context + // Lookup Type 9: Extension positioning + ////////////////////////////////////////////////////////////////////////////////// + private function _applyGPOSvaluerecord($basepos, $Value) + { + + // If current glyph is a mark with a defined width, any XAdvance is considered to REPLACE the character Advance Width + // Test case <div style="font-family:myanmartext">င်္က္ကျြွေိ</div> + if (strpos($this->GlyphClassMarks, $this->OTLdata[$basepos]['hex']) !== false) { + $cw = round($this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$basepos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000); // convert back to font design units + } else { + $cw = 0; + } + + $apos = $this->_getXAdvancePos($basepos); + + if (isset($Value['XAdvance']) && ($Value['XAdvance'] - $cw) != 0) { + // However DON'T REPLACE the character Advance Width if Advance Width is negative + // Test case <div style="font-family: dejavusansmono">ру́сский</div> + if ($Value['XAdvance'] < 0) { + $cw = 0; + } + + // For LTR apply XAdvanceL to the last mark following the base = at $apos + // For RTL apply XAdvanceR to base = at $basepos + if (isset($this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'])) { + $this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'] += $Value['XAdvance'] - $cw; + } else { + $this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'] = $Value['XAdvance'] - $cw; + } + if (isset($this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'])) { + $this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'] += $Value['XAdvance'] - $cw; + } else { + $this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'] = $Value['XAdvance'] - $cw; + } + } + + // Any XPlacement (? and Y Placement) apply to base and marks (from basepos to apos) + for ($a = $basepos; $a <= $apos; $a++) { + if (isset($Value['XPlacement'])) { + if (isset($this->OTLdata[$a]['GPOSinfo']['XPlacement'])) { + $this->OTLdata[$a]['GPOSinfo']['XPlacement'] += $Value['XPlacement']; + } else { + $this->OTLdata[$a]['GPOSinfo']['XPlacement'] = $Value['XPlacement']; + } + } + if (isset($Value['YPlacement'])) { + if (isset($this->OTLdata[$a]['GPOSinfo']['YPlacement'])) { + $this->OTLdata[$a]['GPOSinfo']['YPlacement'] += $Value['YPlacement']; + } else { + $this->OTLdata[$a]['GPOSinfo']['YPlacement'] = $Value['YPlacement']; + } + } + } + } + + // If XAdvance is aplied to $ptr - in order for PDF to position the Advance correctly need to place it on + // the last of any Marks which immediately follow the current glyph + private function _getXAdvancePos($pos) + { + // NB Not all fonts have all marks specified in GlyphClassMarks + // If the current glyph is not a base (but a mark) then ignore this, and apply to the current position + if (strpos($this->GlyphClassMarks, $this->OTLdata[$pos]['hex']) !== false) { + return $pos; + } + + while (isset($this->OTLdata[$pos + 1]['hex']) && strpos($this->GlyphClassMarks, $this->OTLdata[$pos + 1]['hex']) !== false) { + $pos++; + } + return $pos; + } + + private function _applyGPOSsubtable($lookupID, $subtable, $ptr, $currGlyph, $currGID, $subtable_offset, $Type, $Flag, $MarkFilteringSet, $LuCoverage, $tag, $level, $is_old_spec) + { + if (($Flag & 0x0001) == 1) { + $dir = 'RTL'; + } else { // only used for Type 3 + $dir = 'LTR'; + } + + $ignore = $this->_getGCOMignoreString($Flag, $MarkFilteringSet); + + // Lets start + $this->seek($subtable_offset); + $PosFormat = $this->read_ushort(); + + //////////////////////////////////////////////////////////////////////////////// + // LookupType 1: Single adjustment Adjust position of a single glyph (e.g. SmallCaps/Sups/Subs) + //////////////////////////////////////////////////////////////////////////////// + if ($Type == 1) { + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat = $this->read_ushort(); + $Value = $this->_getValueRecord($ValueFormat); + } //=========== + // Format 2: + //=========== + elseif ($PosFormat == 2) { + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat = $this->read_ushort(); + $ValueCount = $this->read_ushort(); + $GlyphPos = $LuCoverage[$currGID]; + $this->skip($GlyphPos * 2 * $this->count_bits($ValueFormat)); + $Value = $this->_getValueRecord($ValueFormat); + } + $this->_applyGPOSvaluerecord($ptr, $Value); + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return 1; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 2: Pair adjustment Adjust position of a pair of glyphs (Kerning) + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 2) { + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat1 = $this->read_ushort(); + $ValueFormat2 = $this->read_ushort(); + $sizeOfPair = ( 2 * $this->count_bits($ValueFormat1) ) + ( 2 * $this->count_bits($ValueFormat2) ); + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + $PairSetCount = $this->read_ushort(); + $PairSetOffset = []; + for ($p = 0; $p < $PairSetCount; $p++) { + $PairSetOffset[] = $subtable_offset + $this->read_ushort(); + } + for ($p = 0; $p < $PairSetCount; $p++) { + if (isset($LuCoverage[$currGID]) && $LuCoverage[$currGID] == $p) { + $this->seek($PairSetOffset[$p]); + //PairSet table + $PairValueCount = $this->read_ushort(); + for ($pv = 0; $pv < $PairValueCount; $pv++) { + //PairValueRecord + $gid = $this->read_ushort(); + $SecondGlyph = $this->glyphToChar($gid); + $FirstGlyph = $this->OTLdata[$ptr]['uni']; + + $checkpos = $ptr; + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + if (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == $SecondGlyph) { + $matchedpos = $checkpos; + } else { + $matchedpos = false; + } + + if ($matchedpos !== false) { + $Value1 = $this->_getValueRecord($ValueFormat1); + $Value2 = $this->_getValueRecord($ValueFormat2); + if ($ValueFormat1) { + $this->_applyGPOSvaluerecord($ptr, $Value1); + } + if ($ValueFormat2) { + $this->_applyGPOSvaluerecord($matchedpos, $Value2); + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return $matchedpos - $ptr + 1; + } + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return $matchedpos - $ptr; + } else { + $this->skip($sizeOfPair); + } + } + } + } + return 0; + } //=========== + // Format 2: + //=========== + elseif ($PosFormat == 2) { + $ClassDef1 = $subtable_offset + $this->read_ushort(); + $ClassDef2 = $subtable_offset + $this->read_ushort(); + $Class1Count = $this->read_ushort(); + $Class2Count = $this->read_ushort(); + + $sizeOfValueRecords = $Class1Count * $Class2Count * $sizeOfPair; + + //$this->skip($sizeOfValueRecords ); ???? NOT NEEDED + // NB Class1Count includes Class 0 even though it is not defined by $ClassDef1 + // i.e. Class1Count = 5; Class1 will contain array(indices 1-4); + $Class1 = $this->_getClassDefinitionTable($ClassDef1); + $Class2 = $this->_getClassDefinitionTable($ClassDef2); + $FirstGlyph = $this->OTLdata[$ptr]['uni']; + $checkpos = $ptr; + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + if (isset($this->OTLdata[$checkpos])) { + $matchedpos = $checkpos; + } else { + return 0; + } + + $SecondGlyph = $this->OTLdata[$matchedpos]['uni']; + for ($i = 0; $i < $Class1Count; $i++) { + if (isset($Class1[$i]) && count($Class1[$i])) { + $FirstClassPos = array_search($FirstGlyph, $Class1[$i]); + if ($FirstClassPos === false) { + continue; + } else { + for ($j = 0; $j < $Class2Count; $j++) { + if (isset($Class2[$j]) && count($Class2[$j])) { + $SecondClassPos = array_search($SecondGlyph, $Class2[$j]); + if ($SecondClassPos === false) { + continue; + } + + // Get ValueRecord[$i][$j] + $offs = ($i * $Class2Count * $sizeOfPair) + ($j * $sizeOfPair); + $this->seek($subtable_offset + 16 + $offs); + + $Value1 = $this->_getValueRecord($ValueFormat1); + $Value2 = $this->_getValueRecord($ValueFormat2); + if ($ValueFormat1) { + $this->_applyGPOSvaluerecord($ptr, $Value1); + } + if ($ValueFormat2) { + $this->_applyGPOSvaluerecord($matchedpos, $Value2); + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return $matchedpos - $ptr + 1; + } + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return $matchedpos - $ptr; + } + } + } + } + } + return 0; + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 3: Cursive attachment Attach cursive glyphs + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 3) { + $this->skip(4); + // Need default XAdvance for glyph + $pdfWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], hexdec($currGlyph)); // DON'T convert back to design units + + $CPos = $LuCoverage[$currGID]; + $this->skip($CPos * 4); + $EntryAnchor = $this->read_ushort(); + $ExitAnchor = $this->read_ushort(); + if ($EntryAnchor != 0) { + $EntryAnchor += $subtable_offset; + list($x, $y) = $this->_getAnchorTable($EntryAnchor); + if ($dir == 'RTL') { + if (round($pdfWidth) == round($x * 1000 / $this->mpdf->CurrentFont['unitsPerEm'])) { + $x = 0; + } else { + $x = $x - ($pdfWidth * $this->mpdf->CurrentFont['unitsPerEm'] / 1000); + } + } + + $this->Entry[$ptr] = ['X' => $x, 'Y' => $y, 'dir' => $dir]; + } + if ($ExitAnchor != 0) { + $ExitAnchor += $subtable_offset; + list($x, $y) = $this->_getAnchorTable($ExitAnchor); + if ($dir == 'LTR') { + if (round($pdfWidth) == round($x * 1000 / $this->mpdf->CurrentFont['unitsPerEm'])) { + $x = 0; + } else { + $x = $x - ($pdfWidth * $this->mpdf->CurrentFont['unitsPerEm'] / 1000); + } + } + $this->Exit[$ptr] = ['X' => $x, 'Y' => $y, 'dir' => $dir]; + } + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return 1; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 4: MarkToBase attachment Attach a combining mark to a base glyph + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 4) { + $MarkCoverage = $subtable_offset + $this->read_ushort(); + //$MarkCoverage is already set in $LuCoverage 00065|00073 etc + $BaseCoverage = $subtable_offset + $this->read_ushort(); + $ClassCount = $this->read_ushort(); // Number of classes defined for marks = Number of mark glyphs in the MarkCoverage table + $MarkArray = $subtable_offset + $this->read_ushort(); // Offset to MarkArray table + $BaseArray = $subtable_offset + $this->read_ushort(); // Offset to BaseArray table + + $this->seek($BaseCoverage); + $BaseGlyphs = implode('|', $this->_getCoverage()); + + $checkpos = $ptr; + $checkpos--; + + // ZZZ93 + // In Lohit-Kannada font (old-spec), rules specify a Type 4 GPOS to attach below-forms to base glyph + // the repositioning does not happen in MS Word, and shouldn't happen comparing with other fonts + // ?Why not + // This Fix blocks the GPOS rule if the "mark" is not actually classified as a mark in the GlyphClasses of GDEF + // but only in Indic old-spec. + // Test cases: ನ್ನು and ಕ್ರೌ + if ($this->shaper == 'I' && $is_old_spec && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) { + return; + } + + + // "To identify the base glyph that combines with a mark, the text-processing client must look backward in the glyph string from the mark to the preceding base glyph." + while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + + if (isset($this->OTLdata[$checkpos]) && strpos($BaseGlyphs, $this->OTLdata[$checkpos]['hex']) !== false) { + $matchedpos = $checkpos; + } else { + $matchedpos = false; + } + + if ($matchedpos !== false) { + // Get the relevant MarkRecord + $MarkPos = $LuCoverage[$currGID]; + $MarkRecord = $this->_getMarkRecord($MarkArray, $MarkPos); // e.g. Array ( [Class] => 0 [AnchorX] => -549 [AnchorY] => 1548 ) + //Mark Class is = $MarkRecord['Class'] + // Get the relevant BaseRecord + $this->seek($BaseArray); + $BaseCount = $this->read_ushort(); + $BasePos = strpos($BaseGlyphs, $this->OTLdata[$matchedpos]['hex']) / 6; + + // Move to the BaseRecord we want + $nSkip = (2 * $BasePos * $ClassCount ); + $this->skip($nSkip); + + // Read BaseRecord we want for appropriate Class + $nSkip = 2 * $MarkRecord['Class']; + $this->skip($nSkip); + $BaseRecordOffset = $BaseArray + $this->read_ushort(); + list($x, $y) = $this->_getAnchorTable($BaseRecordOffset); + $BaseRecord = ['AnchorX' => $x, 'AnchorY' => $y]; // e.g. Array ( [AnchorX] => 660 [AnchorY] => 1556 ) + // Need default XAdvance for Base glyph + $BaseWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000; // convert back to font design units + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $BaseWidth; + // And any intervening (ignored) characters + if (($ptr - $matchedpos) > 1) { + for ($i = $matchedpos + 1; $i < $ptr; $i++) { + $BaseWidthExtra = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$i]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000; // convert back to font design units + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] += $BaseWidthExtra; + } + } + + // Align to previous Glyph by attachment - so need to add to previous placement values + $prevXPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'] : 0); + $prevYPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'] : 0); + + $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $BaseRecord['AnchorX'] - $MarkRecord['AnchorX']; + $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $BaseRecord['AnchorY'] - $MarkRecord['AnchorY']; + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return 1; + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 5: MarkToLigature attachment Attach a combining mark to a ligature + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 5) { + $MarkCoverage = $subtable_offset + $this->read_ushort(); + //$MarkCoverage is already set in $LuCoverage 00065|00073 etc + $LigatureCoverage = $subtable_offset + $this->read_ushort(); + $ClassCount = $this->read_ushort(); // Number of classes defined for marks = Number of mark glyphs in the MarkCoverage table + $MarkArray = $subtable_offset + $this->read_ushort(); // Offset to MarkArray table + $LigatureArray = $subtable_offset + $this->read_ushort(); // Offset to LigatureArray table + + $this->seek($LigatureCoverage); + $LigatureGlyphs = implode('|', $this->_getCoverage()); + + + $checkpos = $ptr; + $checkpos--; + + // "To position a combining mark using a MarkToLigature attachment subtable, the text-processing client must work backward from the mark to the preceding ligature glyph." + while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + + if (isset($this->OTLdata[$checkpos]) && strpos($LigatureGlyphs, $this->OTLdata[$checkpos]['hex']) !== false) { + $matchedpos = $checkpos; + } else { + $matchedpos = false; + } + + if ($matchedpos !== false) { + // Get the relevant MarkRecord + $MarkPos = $LuCoverage[$currGID]; + $MarkRecord = $this->_getMarkRecord($MarkArray, $MarkPos); // e.g. Array ( [Class] => 0 [AnchorX] => -549 [AnchorY] => 1548 ) + //Mark Class is = $MarkRecord['Class'] + // Get the relevant LigatureRecord + $this->seek($LigatureArray); + $LigatureCount = $this->read_ushort(); + $LigaturePos = strpos($LigatureGlyphs, $this->OTLdata[$matchedpos]['hex']) / 6; + + // Move to the LigatureAttach table Record we want + $nSkip = (2 * $LigaturePos); + $this->skip($nSkip); + $LigatureAttachOffset = $LigatureArray + $this->read_ushort(); + $this->seek($LigatureAttachOffset); + $ComponentCount = $this->read_ushort(); + $offsets = []; + for ($comp = 0; $comp < $ComponentCount; $comp++) { + // ComponentRecords + for ($class = 0; $class < $ClassCount; $class++) { + $offsets[$comp][$class] = $this->read_ushort(); + } + } + + // Get the specific component for this mark attachment + if (isset($this->assocLigs[$matchedpos]) && isset($this->assocMarks[$ptr]['ligPos']) && $this->assocMarks[$ptr]['ligPos'] == $matchedpos) { + $component = $this->assocMarks[$ptr]['compID']; + } else { + $component = $ComponentCount - 1; + } + + $offset = $offsets[$component][$MarkRecord['Class']]; + if ($offset != 0) { + $LigatureRecordOffset = $offset + $LigatureAttachOffset; + list($x, $y) = $this->_getAnchorTable($LigatureRecordOffset); + $LigatureRecord = ['AnchorX' => $x, 'AnchorY' => $y]; + + // Need default XAdvance for Ligature glyph + $LigatureWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000; // convert back to font design units + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $LigatureWidth; + // And any intervening (ignored)characters + if (($ptr - $matchedpos) > 1) { + for ($i = $matchedpos + 1; $i < $ptr; $i++) { + $LigatureWidthExtra = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$i]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000; // convert back to font design units + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] += $LigatureWidthExtra; + } + } + + // Align to previous Ligature by attachment - so need to add to previous placement values + if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'])) { + $prevXPlacement = $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']; + } else { + $prevXPlacement = 0; + } + if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'])) { + $prevYPlacement = $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement']; + } else { + $prevYPlacement = 0; + } + + $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $LigatureRecord['AnchorX'] - $MarkRecord['AnchorX']; + $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $LigatureRecord['AnchorY'] - $MarkRecord['AnchorY']; + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return 1; + } + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 6: MarkToMark attachment Attach a combining mark to another mark + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 6) { + $Mark1Coverage = $subtable_offset + $this->read_ushort(); // Combining Mark + //$Mark1Coverage is already set in $LuCoverage 0065|0073 etc + $Mark2Coverage = $subtable_offset + $this->read_ushort(); // Base Mark + $ClassCount = $this->read_ushort(); // Number of classes defined for marks = No. of Combining mark1 glyphs in the MarkCoverage table + $Mark1Array = $subtable_offset + $this->read_ushort(); // Offset to MarkArray table + $Mark2Array = $subtable_offset + $this->read_ushort(); // Offset to Mark2Array table + $this->seek($Mark2Coverage); + $Mark2Glyphs = implode('|', $this->_getCoverage()); + $checkpos = $ptr; + $checkpos--; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + if (isset($this->OTLdata[$checkpos]) && strpos($Mark2Glyphs, $this->OTLdata[$checkpos]['hex']) !== false) { + $matchedpos = $checkpos; + } else { + $matchedpos = false; + } + + if ($matchedpos !== false) { + // Get the relevant MarkRecord + $Mark1Pos = $LuCoverage[$currGID]; + $Mark1Record = $this->_getMarkRecord($Mark1Array, $Mark1Pos); // e.g. Array ( [Class] => 0 [AnchorX] => -549 [AnchorY] => 1548 ) + //Mark Class is = $Mark1Record['Class'] + // Get the relevant Mark2Record + $this->seek($Mark2Array); + $Mark2Count = $this->read_ushort(); + $Mark2Pos = strpos($Mark2Glyphs, $this->OTLdata[$matchedpos]['hex']) / 6; + + // Move to the Mark2Record we want + $nSkip = (2 * $Mark2Pos * $ClassCount ); + $this->skip($nSkip); + + // Read Mark2Record we want for appropriate Class + $nSkip = 2 * $Mark1Record['Class']; + $this->skip($nSkip); + $Mark2RecordOffset = $Mark2Array + $this->read_ushort(); + list($x, $y) = $this->_getAnchorTable($Mark2RecordOffset); + $Mark2Record = ['AnchorX' => $x, 'AnchorY' => $y]; // e.g. Array ( [AnchorX] => 660 [AnchorY] => 1556 ) + // Need default XAdvance for Mark2 glyph + $Mark2Width = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000; // convert back to font design units + // IF combining marks are set on different components of a ligature glyph, do not apply this rule + // Test: arabictypesetting: إِلَىٰٓ + // Test: arabictypesetting: بَّيْنَكُمْ + $prevLig = -1; + $thisLig = -1; + $prevComp = -1; + $thisComp = -1; + if (isset($this->assocMarks[$matchedpos])) { + $prevLig = $this->assocMarks[$matchedpos]['ligPos']; + $prevComp = $this->assocMarks[$matchedpos]['compID']; + } + if (isset($this->assocMarks[$ptr])) { + $thisLig = $this->assocMarks[$ptr]['ligPos']; + $thisComp = $this->assocMarks[$ptr]['compID']; + } + + // However IF Mark2 (first in logical order, i.e. being attached to) is not associated with a base, carry on + // This happens in Indic when the Mark being attached to e.g. [Halant Ma lig] -> MatraU, [U+0B4D + U+B2E as E0F5]-> U+0B41 become E135 + if (!defined("OMIT_OTL_FIX_1") || OMIT_OTL_FIX_1 != 1) { + /* OTL_FIX_1 */ + if (isset($this->assocMarks[$matchedpos]) && ($prevLig != $thisLig || $prevComp != $thisComp )) { + return 0; + } + } else { + /* Original code */ + if ($prevLig != $thisLig || $prevComp != $thisComp) { + return 0; + } + } + + + if (!defined("OMIT_OTL_FIX_2") || OMIT_OTL_FIX_2 != 1) { + /* OTL_FIX_2 */ + if (!isset($this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) || !$this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) { + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $Mark2Width; + } + } + + // ZZZ99Q - Test Case font-family: garuda น้ำ + if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) && $this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) { + $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']; + } + + // Align to previous Mark by attachment - so need to add the previous placement values + $prevXPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'] : 0); + $prevYPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'] : 0); + $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $Mark2Record['AnchorX'] - $Mark1Record['AnchorX']; + $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $Mark2Record['AnchorY'] - $Mark1Record['AnchorY']; + if ($this->debugOTL) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + return 1; + } + return 0; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 7: Context positioning Position one or more glyphs in context + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 7) { + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET."); + } //=========== + // Format 2: + //=========== + elseif ($PosFormat == 2) { + $CoverageTableOffset = $subtable_offset + $this->read_ushort(); + $InputClassDefOffset = $subtable_offset + $this->read_ushort(); + $PosClassSetCnt = $this->read_ushort(); + $PosClassSetOffset = []; + for ($b = 0; $b < $PosClassSetCnt; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $PosClassSetOffset[] = $offset; + } else { + $PosClassSetOffset[] = $subtable_offset + $offset; + } + } + + $InputClasses = $this->_getClasses($InputClassDefOffset); + + for ($s = 0; $s < $PosClassSetCnt; $s++) { // $ChainPosClassSet is ordered by input class-may be NULL + // Select $PosClassSet if currGlyph is in First Input Class + if ($PosClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) { + $this->seek($PosClassSetOffset[$s]); + $PosClassRuleCnt = $this->read_ushort(); + $PosClassRule = []; + for ($b = 0; $b < $PosClassRuleCnt; $b++) { + $PosClassRule[$b] = $PosClassSetOffset[$s] + $this->read_ushort(); + } + + for ($b = 0; $b < $PosClassRuleCnt; $b++) { // EACH RULE + $this->seek($PosClassRule[$b]); + $InputGlyphCount = $this->read_ushort(); + $PosCount = $this->read_ushort(); + + $Input = []; + for ($r = 1; $r < $InputGlyphCount; $r++) { + $Input[$r] = $this->read_ushort(); + } + $inputClass = $s; + + $inputGlyphs = []; + $inputGlyphs[0] = $InputClasses[$inputClass]; + + if ($InputGlyphCount > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) { + $classindex = $Input[$gcl]; + if (isset($InputClasses[$classindex])) { + $inputGlyphs[$gcl] = $InputClasses[$classindex]; + } else { + $inputGlyphs[$gcl] = ''; + } + } + } + + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = []; + for ($gc = 1; $gc <= count($InputClasses); $gc++) { + if (is_array($InputClasses[$gc])) { + $class0excl = $class0excl + $InputClasses[$gc]; + } + } + + $backtrackGlyphs = []; + $lookaheadGlyphs = []; + + $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl); + if ($matched) { + for ($p = 0; $p < $PosCount; $p++) { // EACH LOOKUP + $SequenceIndex[$p] = $this->read_ushort(); + $LookupListIndex[$p] = $this->read_ushort(); + } + + for ($p = 0; $p < $PosCount; $p++) { + // Apply $LookupListIndex at $SequenceIndex + if ($SequenceIndex[$p] >= $InputGlyphCount) { + continue; + } + $lu = $LookupListIndex[$p]; + $luType = $this->GPOSLookups[$lu]['Type']; + $luFlag = $this->GPOSLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SequenceIndex[$p]]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GPOSLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + break; + } + } + } + + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + } + } + + return 0; + } //=========== + // Format 3: + //=========== + elseif ($PosFormat == 3) { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET."); + } else { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported."); + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 8: Chained Context positioning Position one or more glyphs in chained context + //////////////////////////////////////////////////////////////////////////////// + elseif ($Type == 8) { + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET."); + return 0; + } //=========== + // Format 2: + //=========== + elseif ($PosFormat == 2) { + $CoverageTableOffset = $subtable_offset + $this->read_ushort(); + $BacktrackClassDefOffset = $subtable_offset + $this->read_ushort(); + $InputClassDefOffset = $subtable_offset + $this->read_ushort(); + $LookaheadClassDefOffset = $subtable_offset + $this->read_ushort(); + $ChainPosClassSetCnt = $this->read_ushort(); + $ChainPosClassSetOffset = []; + for ($b = 0; $b < $ChainPosClassSetCnt; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $ChainPosClassSetOffset[] = $offset; + } else { + $ChainPosClassSetOffset[] = $subtable_offset + $offset; + } + } + + $BacktrackClasses = $this->_getClasses($BacktrackClassDefOffset); + $InputClasses = $this->_getClasses($InputClassDefOffset); + $LookaheadClasses = $this->_getClasses($LookaheadClassDefOffset); + + for ($s = 0; $s < $ChainPosClassSetCnt; $s++) { // $ChainPosClassSet is ordered by input class-may be NULL + // Select $ChainPosClassSet if currGlyph is in First Input Class + if ($ChainPosClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) { + $this->seek($ChainPosClassSetOffset[$s]); + $ChainPosClassRuleCnt = $this->read_ushort(); + $ChainPosClassRule = []; + for ($b = 0; $b < $ChainPosClassRuleCnt; $b++) { + $ChainPosClassRule[$b] = $ChainPosClassSetOffset[$s] + $this->read_ushort(); + } + + for ($b = 0; $b < $ChainPosClassRuleCnt; $b++) { // EACH RULE + $this->seek($ChainPosClassRule[$b]); + $BacktrackGlyphCount = $this->read_ushort(); + $Backtrack = []; + for ($r = 0; $r < $BacktrackGlyphCount; $r++) { + $Backtrack[$r] = $this->read_ushort(); + } + $InputGlyphCount = $this->read_ushort(); + $Input = []; + for ($r = 1; $r < $InputGlyphCount; $r++) { + $Input[$r] = $this->read_ushort(); + } + $LookaheadGlyphCount = $this->read_ushort(); + $Lookahead = []; + for ($r = 0; $r < $LookaheadGlyphCount; $r++) { + $Lookahead[$r] = $this->read_ushort(); + } + + $inputClass = $s; //??? + + $inputGlyphs = []; + $inputGlyphs[0] = $InputClasses[$inputClass]; + + if ($InputGlyphCount > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) { + $classindex = $Input[$gcl]; + if (isset($InputClasses[$classindex])) { + $inputGlyphs[$gcl] = $InputClasses[$classindex]; + } else { + $inputGlyphs[$gcl] = ''; + } + } + } + + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = []; + for ($gc = 1; $gc <= count($InputClasses); $gc++) { + if (isset($InputClasses[$gc]) && is_array($InputClasses[$gc])) { + $class0excl = $class0excl + $InputClasses[$gc]; + } + } + + if ($BacktrackGlyphCount) { + $backtrackGlyphs = []; + for ($gcl = 0; $gcl < $BacktrackGlyphCount; $gcl++) { + $classindex = $Backtrack[$gcl]; + if (isset($BacktrackClasses[$classindex])) { + $backtrackGlyphs[$gcl] = $BacktrackClasses[$classindex]; + } else { + $backtrackGlyphs[$gcl] = ''; + } + } + } else { + $backtrackGlyphs = []; + } + + // Class 0 contains all the glyphs NOT in the other classes + $bclass0excl = []; + for ($gc = 1; $gc <= count($BacktrackClasses); $gc++) { + if (isset($BacktrackClasses[$gc]) && is_array($BacktrackClasses[$gc])) { + $bclass0excl = $bclass0excl + $BacktrackClasses[$gc]; + } + } + + if ($LookaheadGlyphCount) { + $lookaheadGlyphs = []; + for ($gcl = 0; $gcl < $LookaheadGlyphCount; $gcl++) { + $classindex = $Lookahead[$gcl]; + if (isset($LookaheadClasses[$classindex])) { + $lookaheadGlyphs[$gcl] = $LookaheadClasses[$classindex]; + } else { + $lookaheadGlyphs[$gcl] = ''; + } + } + } else { + $lookaheadGlyphs = []; + } + + // Class 0 contains all the glyphs NOT in the other classes + $lclass0excl = []; + for ($gc = 1; $gc <= count($LookaheadClasses); $gc++) { + if (isset($LookaheadClasses[$gc]) && is_array($LookaheadClasses[$gc])) { + $lclass0excl = $lclass0excl + $LookaheadClasses[$gc]; + } + } + + $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl, $bclass0excl, $lclass0excl); + if ($matched) { + $PosCount = $this->read_ushort(); + $SequenceIndex = []; + $LookupListIndex = []; + for ($p = 0; $p < $PosCount; $p++) { // EACH LOOKUP + $SequenceIndex[$p] = $this->read_ushort(); + $LookupListIndex[$p] = $this->read_ushort(); + } + + for ($p = 0; $p < $PosCount; $p++) { + // Apply $LookupListIndex at $SequenceIndex + if ($SequenceIndex[$p] >= $InputGlyphCount) { + continue; + } + $lu = $LookupListIndex[$p]; + $luType = $this->GPOSLookups[$lu]['Type']; + $luFlag = $this->GPOSLookups[$lu]['Flag']; + $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet']; + + $luptr = $matched[$SequenceIndex[$p]]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GPOSLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + break; + } + } + } + + if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) { + return $shift; + } /* OTL_FIX_3 */ + else { + return $InputGlyphCount; // should be + matched ignores in Input Sequence + } + } + } + } + } + + return 0; + } //=========== + // Format 3: + //=========== + elseif ($PosFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $InputGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $InputGlyphCount; $b++) { + $CoverageInputOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $LookaheadGlyphCount = $this->read_ushort(); + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $PosCount = $this->read_ushort(); + $save_pos = $this->_pos; // Save the point just after PosCount + + $CoverageBacktrackGlyphs = []; + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $this->seek($CoverageBacktrackOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageBacktrackGlyphs[$b] = implode("|", $glyphs); + } + $CoverageInputGlyphs = []; + for ($b = 0; $b < $InputGlyphCount; $b++) { + $this->seek($CoverageInputOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageInputGlyphs[$b] = implode("|", $glyphs); + } + $CoverageLookaheadGlyphs = []; + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $this->seek($CoverageLookaheadOffset[$b]); + $glyphs = $this->_getCoverage(); + $CoverageLookaheadGlyphs[$b] = implode("|", $glyphs); + } + $matched = $this->checkContextMatchMultiple($CoverageInputGlyphs, $CoverageBacktrackGlyphs, $CoverageLookaheadGlyphs, $ignore, $ptr); + if ($matched) { + $this->seek($save_pos); // Return to just after PosCount + for ($p = 0; $p < $PosCount; $p++) { + // PosLookupRecord + $PosLookupRecord[$p]['SequenceIndex'] = $this->read_ushort(); + $PosLookupRecord[$p]['LookupListIndex'] = $this->read_ushort(); + } + for ($p = 0; $p < $PosCount; $p++) { + // Apply $PosLookupRecord[$p]['LookupListIndex'] at $PosLookupRecord[$p]['SequenceIndex'] + if ($PosLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) { + continue; + } + $lu = $PosLookupRecord[$p]['LookupListIndex']; + $luType = $this->GPOSLookups[$lu]['Type']; + $luFlag = $this->GPOSLookups[$lu]['Flag']; + if (isset($this->GPOSLookups[$lu]['MarkFilteringSet'])) { + $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet']; + } else { + $luMarkFilteringSet = ''; + } + + $luptr = $matched[$PosLookupRecord[$p]['SequenceIndex']]; + $lucurrGlyph = $this->OTLdata[$luptr]['hex']; + $lucurrGID = $this->OTLdata[$luptr]['uni']; + + foreach ($this->GPOSLookups[$lu]['Subtables'] as $luc => $lusubtable_offset) { + $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec); + if ($this->debugOTL && $shift) { + $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level); + } + if ($shift) { + break; + } + } + } + } + } else { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported."); + } + } else { + throw new \Mpdf\MpdfException("GPOS Lookup Type " . $Type . " not supported."); + } + } + + ////////////////////////////////////////////////////////////////////////////////// + // GPOS / GSUB / GCOM (common) functions + ////////////////////////////////////////////////////////////////////////////////// + private function checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr) + { + // Input etc are single numbers - GSUB Format 6.1 + // Input starts with (1=>xxx) + // return false if no match, else an array of ptr for matches (0=>0, 1=>3,...) + + $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0); + + // BACKTRACK + $checkpos = $ptr; + for ($i = 0; $i < count($Backtrack); $i++) { + $checkpos--; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || $this->OTLdata[$checkpos]['uni'] != $Backtrack[$i]) { + return false; + } + } + + // INPUT + $matched = [0 => $ptr]; + $checkpos = $ptr; + for ($i = 1; $i < count($Input); $i++) { + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } elseif (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == $Input[$i]) { + $matched[] = $checkpos; + } else { + return false; + } + } + + // LOOKAHEAD + for ($i = 0; $i < count($Lookahead); $i++) { + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || $this->OTLdata[$checkpos]['uni'] != $Lookahead[$i]) { + return false; + } + } + + return $matched; + } + + private function checkContextMatchMultiple($Input, $Backtrack, $Lookahead, $ignore, $ptr, $class0excl = '', $bclass0excl = '', $lclass0excl = '') + { + // Input etc are string/array of glyph strings - GSUB Format 5.2, 5.3, 6.2, 6.3, GPOS Format 7.2, 7.3, 8.2, 8.3 + // Input starts with (1=>xxx) + // return false if no match, else an array of ptr for matches (0=>0, 1=>3,...) + // $class0excl is the string of glyphs in all classes except Class 0 (GSUB 5.2, 6.2, GPOS 7.2, 8.2) + // $bclass0excl & $lclass0excl are the same for lookahead and backtrack (GSUB 6.2, GPOS 8.2) + + $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0); + + // BACKTRACK + $checkpos = $ptr; + for ($i = 0; $i < count($Backtrack); $i++) { + $checkpos--; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Class 0 specified, matches anything NOT in $bclass0excl + elseif (!$Backtrack[$i] && isset($this->OTLdata[$checkpos]) && strpos($bclass0excl, $this->OTLdata[$checkpos]['hex']) !== false) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || strpos($Backtrack[$i], $this->OTLdata[$checkpos]['hex']) === false) { + return false; + } + } + + // INPUT + $matched = [0 => $ptr]; + $checkpos = $ptr; + for ($i = 1; $i < count($Input); $i++) { // Start at 1 - already matched the first InputGlyph + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Input Class 0 specified, matches anything NOT in $class0excl + elseif (!$Input[$i] && isset($this->OTLdata[$checkpos]) && strpos($class0excl, $this->OTLdata[$checkpos]['hex']) === false) { + $matched[] = $checkpos; + } elseif (isset($this->OTLdata[$checkpos]) && strpos($Input[$i], $this->OTLdata[$checkpos]['hex']) !== false) { + $matched[] = $checkpos; + } else { + return false; + } + } + + // LOOKAHEAD + for ($i = 0; $i < count($Lookahead); $i++) { + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Class 0 specified, matches anything NOT in $lclass0excl + elseif (!$Lookahead[$i] && isset($this->OTLdata[$checkpos]) && strpos($lclass0excl, $this->OTLdata[$checkpos]['hex']) !== false) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || strpos($Lookahead[$i], $this->OTLdata[$checkpos]['hex']) === false) { + return false; + } + } + return $matched; + } + + private function checkContextMatchMultipleUni($Input, $Backtrack, $Lookahead, $ignore, $ptr, $class0excl = [], $bclass0excl = [], $lclass0excl = []) + { + // Input etc are array of glyphs - GSUB Format 5.2, 5.3, 6.2, 6.3, GPOS Format 7.2, 7.3, 8.2, 8.3 + // Input starts with (1=>xxx) + // return false if no match, else an array of ptr for matches (0=>0, 1=>3,...) + // $class0excl is array of glyphs in all classes except Class 0 (GSUB 5.2, 6.2, GPOS 7.2, 8.2) + // $bclass0excl & $lclass0excl are the same for lookahead and backtrack (GSUB 6.2, GPOS 8.2) + + $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0); + + // BACKTRACK + $checkpos = $ptr; + for ($i = 0; $i < count($Backtrack); $i++) { + $checkpos--; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos--; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Class 0 specified, matches anything NOT in $bclass0excl + elseif (!$Backtrack[$i] && isset($this->OTLdata[$checkpos]) && isset($bclass0excl[$this->OTLdata[$checkpos]['uni']])) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || !isset($Backtrack[$i][$this->OTLdata[$checkpos]['uni']])) { + return false; + } + } + + // INPUT + $matched = [0 => $ptr]; + $checkpos = $ptr; + for ($i = 1; $i < count($Input); $i++) { // Start at 1 - already matched the first InputGlyph + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Input Class 0 specified, matches anything NOT in $class0excl + elseif (!$Input[$i] && isset($this->OTLdata[$checkpos]) && !isset($class0excl[$this->OTLdata[$checkpos]['uni']])) { + $matched[] = $checkpos; + } elseif (isset($this->OTLdata[$checkpos]) && isset($Input[$i][$this->OTLdata[$checkpos]['uni']])) { + $matched[] = $checkpos; + } else { + return false; + } + } + + // LOOKAHEAD + for ($i = 0; $i < count($Lookahead); $i++) { + $checkpos++; + while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) { + $checkpos++; + } + // If outside scope of current syllable - return no match + if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) { + return false; + } // If Class 0 specified, matches anything NOT in $lclass0excl + elseif (!$Lookahead[$i] && isset($this->OTLdata[$checkpos]) && isset($lclass0excl[$this->OTLdata[$checkpos]['uni']])) { + return false; + } elseif (!isset($this->OTLdata[$checkpos]) || !isset($Lookahead[$i][$this->OTLdata[$checkpos]['uni']])) { + return false; + } + } + return $matched; + } + + private function _getClassDefinitionTable($offset) + { + if (isset($this->LuDataCache[$this->fontkey][$offset])) { + $GlyphByClass = $this->LuDataCache[$this->fontkey][$offset]; + } else { + $this->seek($offset); + $ClassFormat = $this->read_ushort(); + $GlyphClass = []; + $GlyphByClass = []; + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $GlyphClass[$i]['startGlyphID'] = $StartGlyph + $i; + $GlyphClass[$i]['endGlyphID'] = $StartGlyph + $i; + $GlyphClass[$i]['class'] = $this->read_ushort(); + for ($g = $GlyphClass[$i]['startGlyphID']; $g <= $GlyphClass[$i]['endGlyphID']; $g++) { + $GlyphByClass[$GlyphClass[$i]['class']][] = $this->glyphToChar($g); + } + } + } elseif ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $GlyphClass[$i]['startGlyphID'] = $this->read_ushort(); + $GlyphClass[$i]['endGlyphID'] = $this->read_ushort(); + $GlyphClass[$i]['class'] = $this->read_ushort(); + for ($g = $GlyphClass[$i]['startGlyphID']; $g <= $GlyphClass[$i]['endGlyphID']; $g++) { + $GlyphByClass[$GlyphClass[$i]['class']][] = $this->glyphToChar($g); + } + } + } + ksort($GlyphByClass); + $this->LuDataCache[$this->fontkey][$offset] = $GlyphByClass; + } + return $GlyphByClass; + } + + private function count_bits($n) + { + for ($c = 0; $n; $c++) { + $n &= $n - 1; // clear the least significant bit set + } + return $c; + } + + private function _getValueRecord($ValueFormat) + { + // Common ValueRecord for GPOS + // Only returns 3 possible: $vra['XPlacement'] $vra['YPlacement'] $vra['XAdvance'] + $vra = []; + // Horizontal adjustment for placement - in design units + if (($ValueFormat & 0x0001) == 0x0001) { + $vra['XPlacement'] = $this->read_short(); + } + // Vertical adjustment for placement - in design units + if (($ValueFormat & 0x0002) == 0x0002) { + $vra['YPlacement'] = $this->read_short(); + } + // Horizontal adjustment for advance - in design units (only used for horizontal writing) + if (($ValueFormat & 0x0004) == 0x0004) { + $vra['XAdvance'] = $this->read_short(); + } + // Vertical adjustment for advance - in design units (only used for vertical writing) + if (($ValueFormat & 0x0008) == 0x0008) { + $this->read_short(); + } + // Offset to Device table for horizontal placement-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0010) == 0x0010) { + $this->read_ushort(); + } + // Offset to Device table for vertical placement-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0020) == 0x0020) { + $this->read_ushort(); + } + // Offset to Device table for horizontal advance-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0040) == 0x0040) { + $this->read_ushort(); + } + // Offset to Device table for vertical advance-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0080) == 0x0080) { + $this->read_ushort(); + } + return $vra; + } + + private function _getAnchorTable($offset = 0) + { + if ($offset) { + $this->seek($offset); + } + $AnchorFormat = $this->read_ushort(); + $XCoordinate = $this->read_short(); + $YCoordinate = $this->read_short(); + // Format 2 specifies additional link to contour point; Format 3 additional Device table + return [$XCoordinate, $YCoordinate]; + } + + private function _getMarkRecord($offset, $MarkPos) + { + $this->seek($offset); + $MarkCount = $this->read_ushort(); + $this->skip($MarkPos * 4); + $Class = $this->read_ushort(); + $MarkAnchor = $offset + $this->read_ushort(); // = Offset to anchor table + list($x, $y) = $this->_getAnchorTable($MarkAnchor); + $MarkRecord = ['Class' => $Class, 'AnchorX' => $x, 'AnchorY' => $y]; + return $MarkRecord; + } + + private function _getGCOMignoreString($flag, $MarkFilteringSet) + { + // If ignoreFlag set, combine all ignore glyphs into -> "(?:( 0FBA1| 0FBA2| 0FBA3)*)" + // else "()" + // for Input - set on secondary Lookup table if in Context, and set Backtrack and Lookahead on Context Lookup + $str = ""; + $ignoreflag = 0; + + // Flag & 0xFF?? = MarkAttachmentType + if ($flag & 0xFF00) { + // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" + // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table + $MarkAttachmentType = $flag >> 8; + $ignoreflag = $flag; + $str = $this->MarkAttachmentType[$MarkAttachmentType]; + } + + // Flag & 0x0010 = UseMarkFilteringSet + if ($flag & 0x0010) { + throw new \Mpdf\MpdfException("This font [" . $this->fontkey . "] contains MarkGlyphSets - Not tested yet"); + // Change also in ttfontsuni.php + if ($MarkFilteringSet == '') { + throw new \Mpdf\MpdfException("This font [" . $this->fontkey . "] contains MarkGlyphSets - but MarkFilteringSet not set"); + } + $str = $this->MarkGlyphSets[$MarkFilteringSet]; + } + + // If Ignore Marks set, supercedes any above + // Flag & 0x0008 = Ignore Marks - (unless already done with MarkAttachmentType) + if (($flag & 0x0008) == 0x0008 && ($flag & 0xFF00) == 0) { + $ignoreflag = 8; + $str = $this->GlyphClassMarks; + } + + // Flag & 0x0004 = Ignore Ligatures + if (($flag & 0x0004) == 0x0004) { + $ignoreflag += 4; + if ($str) { + $str .= "|"; + } + $str .= $this->GlyphClassLigatures; + } + // Flag & 0x0002 = Ignore BaseGlyphs + if (($flag & 0x0002) == 0x0002) { + $ignoreflag += 2; + if ($str) { + $str .= "|"; + } + $str .= $this->GlyphClassBases; + } + if ($str) { + return "((?:(?:" . $str . "))*)"; + } else { + return "()"; + } + } + + private function _checkGCOMignore($flag, $glyph, $MarkFilteringSet) + { + $ignore = false; + // Flag & 0x0008 = Ignore Marks - (unless already done with MarkAttachmentType) + if (($flag & 0x0008 && ($flag & 0xFF00) == 0) && strpos($this->GlyphClassMarks, $glyph)) { + $ignore = true; + } + if (($flag & 0x0004) && strpos($this->GlyphClassLigatures, $glyph)) { + $ignore = true; + } + if (($flag & 0x0002) && strpos($this->GlyphClassBases, $glyph)) { + $ignore = true; + } + // Flag & 0xFF?? = MarkAttachmentType + if ($flag & 0xFF00) { + // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" + // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table + if (strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) { + $ignore = true; + } + } + // Flag & 0x0010 = UseMarkFilteringSet + if (($flag & 0x0010) && strpos($this->MarkGlyphSets[$MarkFilteringSet], $glyph)) { + $ignore = true; + } + return $ignore; + } + + /** + * Bidi algorithm + * + * These functions are called from mpdf after GSUB/GPOS has taken place + * At this stage the bidi-type is in string form + * + * Bidirectional Character Types + * ============================= + * Type Description General Scope + * Strong + * L Left-to-Right LRM, most alphabetic, syllabic, Han ideographs, non-European or non-Arabic digits, ... + * LRE Left-to-Right Embedding LRE + * LRO Left-to-Right Override LRO + * R Right-to-Left RLM, Hebrew alphabet, and related punctuation + * AL Right-to-Left Arabic Arabic, Thaana, and Syriac alphabets, most punctuation specific to those scripts, ... + * RLE Right-to-Left Embedding RLE + * RLO Right-to-Left Override RLO + * Weak + * PDF Pop Directional Format PDF + * EN European Number European digits, Eastern Arabic-Indic digits, ... + * ES European Number Separator Plus sign, minus sign + * ET European Number Terminator Degree sign, currency symbols, ... + * AN Arabic Number Arabic-Indic digits, Arabic decimal and thousands separators, ... + * CS Common Number Separator Colon, comma, full stop (period), No-break space, ... + * NSM Nonspacing Mark Characters marked Mn (Nonspacing_Mark) and Me (Enclosing_Mark) in the Unicode Character Database + * BN Boundary Neutral Default ignorables, non-characters, and control characters, other than those explicitly given other types. + * Neutral + * B Paragraph Separator Paragraph separator, appropriate Newline Functions, higher-level protocol paragraph determination + * S Segment Separator Tab + * WS Whitespace Space, figure space, line separator, form feed, General Punctuation spaces, ... + * ON Other Neutrals All other characters, including OBJECT REPLACEMENT CHARACTER + */ + public function bidiSort($ta, $str, $dir, &$chunkOTLdata, $useGPOS) + { + + $pel = 0; // paragraph embedding level + $maxlevel = 0; + $numchars = count($chunkOTLdata['char_data']); + + // Set the initial paragraph embedding level + if ($dir == 'rtl') { + $pel = 1; + } else { + $pel = 0; + } + + // X1. Begin by setting the current embedding level to the paragraph embedding level. Set the directional override status to neutral. + // Current Embedding Level + $cel = $pel; + // directional override status (-1 is Neutral) + $dos = -1; + $remember = []; + + // Array of characters data + $chardata = []; + + // Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase. + // In the resolution of levels in rules I1 and I2, the maximum embedding level of 62 can be reached. + for ($i = 0; $i < $numchars; ++$i) { + if ($chunkOTLdata['char_data'][$i]['uni'] == 8235) { // RLE + // X2. With each RLE, compute the least greater odd embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + ($cel % 2) + 1; + if ($next_level < 62) { + $remember[] = ['num' => 8235, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = -1; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8234) { // LRE + // X3. With each LRE, compute the least greater even embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + 2 - ($cel % 2); + if ($next_level < 62) { + $remember[] = ['num' => 8234, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = -1; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8238) { // RLO + // X4. With each RLO, compute the least greater odd embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to right-to-left. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + ($cel % 2) + 1; + if ($next_level < 62) { + $remember[] = ['num' => 8238, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = Ucdn::BIDI_CLASS_R; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8237) { // LRO + // X5. With each LRO, compute the least greater even embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to left-to-right. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + 2 - ($cel % 2); + if ($next_level < 62) { + $remember[] = ['num' => 8237, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = Ucdn::BIDI_CLASS_L; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8236) { // PDF + // X7. With each PDF, determine the matching embedding or override code. If there was a valid matching code, restore (pop) the last remembered (pushed) embedding level and directional override. + if (count($remember)) { + $last = count($remember) - 1; + if (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) || + ($remember[$last]['num'] == 8237)) { + $match = array_pop($remember); + $cel = $match['cel']; + $dos = $match['dos']; + } + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 10) { // NEW LINE + // Reset to start values + $cel = $pel; + $dos = -1; + $remember = []; + } else { + // X6. For all types besides RLE, LRE, RLO, LRO, and PDF: + // a. Set the level of the current character to the current embedding level. + // b. When the directional override status is not neutral, reset the current character type to directional override status. + if ($dos != -1) { + $chardir = $dos; + } else { + $chardir = $chunkOTLdata['char_data'][$i]['bidi_class']; + } + // stores string characters and other information + if (isset($chunkOTLdata['GPOSinfo'][$i])) { + $gpos = $chunkOTLdata['GPOSinfo'][$i]; + } else { + $gpos = ''; + } + $chardata[] = ['char' => $chunkOTLdata['char_data'][$i]['uni'], 'level' => $cel, 'type' => $chardir, 'group' => $chunkOTLdata['group'][$i], 'GPOSinfo' => $gpos]; + } + } + + $numchars = count($chardata); + + // X8. All explicit directional embeddings and overrides are completely terminated at the end of each paragraph. + // Paragraph separators are not included in the embedding. + // X9. Remove all RLE, LRE, RLO, LRO, and PDF codes. + // This is effectively done by only saving other codes to chardata + // X10. Determine the start-of-sequence (sor) and end-of-sequence (eor) types, either L or R, for each isolating run sequence. These depend on the higher of the two levels on either side of the sequence boundary: + // For sor, compare the level of the first character in the sequence with the level of the character preceding it in the paragraph or if there is none, with the paragraph embedding level. + // For eor, compare the level of the last character in the sequence with the level of the character following it in the paragraph or if there is none, with the paragraph embedding level. + // If the higher level is odd, the sor or eor is R; otherwise, it is L. + + $prelevel = $pel; + $postlevel = $pel; + $cel = $prelevel; // current embedding level + for ($i = 0; $i < $numchars; ++$i) { + $level = $chardata[$i]['level']; + if ($i == 0) { + $left = $prelevel; + } else { + $left = $chardata[$i - 1]['level']; + } + if ($i == ($numchars - 1)) { + $right = $postlevel; + } else { + $right = $chardata[$i + 1]['level']; + } + $chardata[$i]['sor'] = max($left, $level) % 2 ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + $chardata[$i]['eor'] = max($right, $level) % 2 ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + } + + + + // 3.3.3 Resolving Weak Types + // Weak types are now resolved one level run at a time. At level run boundaries where the type of the character on the other side of the boundary is required, the type assigned to sor or eor is used. + // Nonspacing marks are now resolved based on the previous characters. + // W1. Examine each nonspacing mark (NSM) in the level run, and change the type of the NSM to the type of the previous character. If the NSM is at the start of the level run, it will get the type of sor. + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_NSM) { + if ($i == 0 || $chardata[$i]['level'] != $chardata[$i - 1]['level']) { + $chardata[$i]['type'] = $chardata[$i]['sor']; + } else { + $chardata[$i]['type'] = $chardata[($i - 1)]['type']; + } + } + } + + // W2. Search backward from each instance of a European number until the first strong type (R, L, AL, or sor) is found. If an AL is found, change the type of the European number to Arabic number. + $prevlevel = -1; + $levcount = 0; + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN) { + $found = false; + for ($j = $levcount; $j >= 0; $j--) { + if ($chardata[$j]['type'] == Ucdn::BIDI_CLASS_AL) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_AN; + $found = true; + break; + } elseif (($chardata[$j]['type'] == Ucdn::BIDI_CLASS_L) || ($chardata[$j]['type'] == Ucdn::BIDI_CLASS_R)) { + $found = true; + break; + } + } + } + if ($chardata[$i]['level'] != $prevlevel) { + $levcount = 0; + } else { + ++$levcount; + } + $prevlevel = $chardata[$i]['level']; + } + + // W3. Change all ALs to R. + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_AL) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_R; + } + } + + // W4. A single European separator between two European numbers changes to a European number. A single common separator between two numbers of the same type changes to that type. + for ($i = 1; $i < $numchars; ++$i) { + if (($i + 1) < $numchars && $chardata[($i)]['level'] == $chardata[($i + 1)]['level'] && $chardata[($i)]['level'] == $chardata[($i - 1)]['level']) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ES && $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_EN && $chardata[($i + 1)]['type'] == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } elseif ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS && $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_EN && $chardata[($i + 1)]['type'] == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } elseif ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS && $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_AN && $chardata[($i + 1)]['type'] == Ucdn::BIDI_CLASS_AN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_AN; + } + } + } + + // W5. A sequence of European terminators adjacent to European numbers changes to all European numbers. + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ET) { + if ($i > 0 && $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_EN && $chardata[($i)]['level'] == $chardata[($i - 1)]['level']) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } else { + $j = $i + 1; + while ($j < $numchars && $chardata[$j]['level'] == $chardata[$i]['level']) { + if ($chardata[$j]['type'] == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + break; + } elseif ($chardata[$j]['type'] != Ucdn::BIDI_CLASS_ET) { + break; + } + ++$j; + } + } + } + } + + // W6. Otherwise, separators and terminators change to Other Neutral. + for ($i = 0; $i < $numchars; ++$i) { + if (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ET) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ES) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS)) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_ON; + } + } + + //W7. Search backward from each instance of a European number until the first strong type (R, L, or sor) is found. If an L is found, then change the type of the European number to L. + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN) { + if ($i == 0) { // Start of Level run + if ($chardata[$i]['sor'] == Ucdn::BIDI_CLASS_L) { + $chardata[$i]['type'] = $chardata[$i]['sor']; + } + } else { + for ($j = $i - 1; $j >= 0; $j--) { + if ($chardata[$j]['level'] != $chardata[$i]['level']) { // Level run boundary + if ($chardata[$j + 1]['sor'] == Ucdn::BIDI_CLASS_L) { + $chardata[$i]['type'] = $chardata[$j + 1]['sor']; + } + break; + } elseif ($chardata[$j]['type'] == Ucdn::BIDI_CLASS_L) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_L; + break; + } elseif ($chardata[$j]['type'] == Ucdn::BIDI_CLASS_R) { + break; + } + } + } + } + } + + // N1. A sequence of neutrals takes the direction of the surrounding strong text if the text on both sides has the same direction. European and Arabic numbers act as if they were R in terms of their influence on neutrals. Start-of-level-run (sor) and end-of-level-run (eor) are used at level run boundaries. + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ON || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_WS) { + $left = -1; + // LEFT + if ($i == 0) { // first char + $left = $chardata[($i)]['sor']; + } elseif ($chardata[($i - 1)]['level'] != $chardata[($i)]['level']) { // run boundary + $left = $chardata[($i)]['sor']; + } elseif ($chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_L) { + $left = Ucdn::BIDI_CLASS_L; + } elseif ($chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_R || $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_EN || $chardata[($i - 1)]['type'] == Ucdn::BIDI_CLASS_AN) { + $left = Ucdn::BIDI_CLASS_R; + } + // RIGHT + $right = -1; + $j = $i; + // move to the right of any following neutrals OR hit a run boundary + while (($chardata[$j]['type'] == Ucdn::BIDI_CLASS_ON || $chardata[$j]['type'] == Ucdn::BIDI_CLASS_WS) && $j <= ($numchars - 1)) { + if ($j == ($numchars - 1)) { // last char + $right = $chardata[($j)]['eor']; + break; + } elseif ($chardata[($j + 1)]['level'] != $chardata[($j)]['level']) { // run boundary + $right = $chardata[($j)]['eor']; + break; + } elseif ($chardata[($j + 1)]['type'] == Ucdn::BIDI_CLASS_L) { + $right = Ucdn::BIDI_CLASS_L; + break; + } elseif ($chardata[($j + 1)]['type'] == Ucdn::BIDI_CLASS_R || $chardata[($j + 1)]['type'] == Ucdn::BIDI_CLASS_EN || $chardata[($j + 1)]['type'] == Ucdn::BIDI_CLASS_AN) { + $right = Ucdn::BIDI_CLASS_R; + break; + } + $j++; + } + if ($left > -1 && $left == $right) { + $chardata[$i]['orig_type'] = $chardata[$i]['type']; // Need to store the original 'WS' for reference in L1 below + $chardata[$i]['type'] = $left; + } + } + } + + // N2. Any remaining neutrals take the embedding direction + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ON || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_WS) { + $chardata[$i]['type'] = ($chardata[$i]['level'] % 2) ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + $chardata[$i]['orig_type'] = $chardata[$i]['type']; // Need to store the original 'WS' for reference in L1 below + } + } + + // I1. For all characters with an even (left-to-right) embedding direction, those of type R go up one level and those of type AN or EN go up two levels. + // I2. For all characters with an odd (right-to-left) embedding direction, those of type L, EN or AN go up one level. + for ($i = 0; $i < $numchars; ++$i) { + $odd = $chardata[$i]['level'] % 2; + if ($odd) { + if (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_L) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_AN) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN)) { + $chardata[$i]['level'] += 1; + } + } else { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_R) { + $chardata[$i]['level'] += 1; + } elseif (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_AN) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN)) { + $chardata[$i]['level'] += 2; + } + } + $maxlevel = max($chardata[$i]['level'], $maxlevel); + } + + // NB + // Separate into lines at this point************ + // + // L1. On each line, reset the embedding level of the following characters to the paragraph embedding level: + // 1. Segment separators (Tab) 'S', + // 2. Paragraph separators 'B', + // 3. Any sequence of whitespace characters 'WS' preceding a segment separator or paragraph separator, and + // 4. Any sequence of whitespace characters 'WS' at the end of the line. + // The types of characters used here are the original types, not those modified by the previous phase cf N1 and N2******* + // Because a Paragraph Separator breaks lines, there will be at most one per line, at the end of that line. + + for ($i = ($numchars - 1); $i > 0; $i--) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_WS || (isset($chardata[$i]['orig_type']) && $chardata[$i]['orig_type'] == Ucdn::BIDI_CLASS_WS)) { + $chardata[$i]['level'] = $pel; + } else { + break; + } + } + + + // L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher. + for ($j = $maxlevel; $j > 0; $j--) { + $ordarray = []; + $revarr = []; + $onlevel = false; + for ($i = 0; $i < $numchars; ++$i) { + if ($chardata[$i]['level'] >= $j) { + $onlevel = true; + + // L4. A character is depicted by a mirrored glyph if and only if (a) the resolved directionality of that character is R, and (b) the Bidi_Mirrored property value of that character is true. + if (isset(Ucdn::$mirror_pairs[$chardata[$i]['char']]) && $chardata[$i]['type'] == Ucdn::BIDI_CLASS_R) { + $chardata[$i]['char'] = Ucdn::$mirror_pairs[$chardata[$i]['char']]; + } + + $revarr[] = $chardata[$i]; + } else { + if ($onlevel) { + $revarr = array_reverse($revarr); + $ordarray = array_merge($ordarray, $revarr); + $revarr = []; + $onlevel = false; + } + $ordarray[] = $chardata[$i]; + } + } + if ($onlevel) { + $revarr = array_reverse($revarr); + $ordarray = array_merge($ordarray, $revarr); + } + $chardata = $ordarray; + } + + $group = ''; + $e = ''; + $GPOS = []; + $cctr = 0; + $rtl_content = 0x0; + foreach ($chardata as $cd) { + $e .= UtfString::code2utf($cd['char']); + $group .= $cd['group']; + if ($useGPOS && is_array($cd['GPOSinfo'])) { + $GPOS[$cctr] = $cd['GPOSinfo']; + $GPOS[$cctr]['wDir'] = ($cd['level'] % 2) ? 'RTL' : 'LTR'; + } + if ($cd['type'] == Ucdn::BIDI_CLASS_L) { + $rtl_content |= 1; + } elseif ($cd['type'] == Ucdn::BIDI_CLASS_R) { + $rtl_content |= 2; + } + $cctr++; + } + + + $chunkOTLdata['group'] = $group; + if ($useGPOS) { + $chunkOTLdata['GPOSinfo'] = $GPOS; + } + + return [$e, $rtl_content]; + } + + /** + * The following versions for BidiSort work on amalgamated chunks to process the whole paragraph + * + * Firstly set the level in the OTLdata - called from fn printbuffer() [_bidiPrepare] + * Secondly re-order - called from fn writeFlowingBlock and FinishFlowingBlock, when already divided into lines. [_bidiReorder] + */ + public function bidiPrepare(&$para, $dir) + { + + // Set the initial paragraph embedding level + $pel = 0; // paragraph embedding level + if ($dir == 'rtl') { + $pel = 1; + } + + // X1. Begin by setting the current embedding level to the paragraph embedding level. Set the directional override status to neutral. + // Current Embedding Level + $cel = $pel; + // directional override status (-1 is Neutral) + $dos = -1; + $remember = []; + $controlchars = false; + $strongrtl = false; + $diid = 0; // direction isolate ID + $dictr = 0; // direction isolate counter + // Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase. + // In the resolution of levels in rules I1 and I2, the maximum embedding level of 62 can be reached. + $numchunks = count($para); + for ($nc = 0; $nc < $numchunks; $nc++) { + $chunkOTLdata = & $para[$nc][18]; + + $numchars = count($chunkOTLdata['char_data']); + for ($i = 0; $i < $numchars; ++$i) { + if ($chunkOTLdata['char_data'][$i]['uni'] == 8235) { // RLE + // X2. With each RLE, compute the least greater odd embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + ($cel % 2) + 1; + if ($next_level < 62) { + $remember[] = ['num' => 8235, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = -1; + $controlchars = true; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8234) { // LRE + // X3. With each LRE, compute the least greater even embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + 2 - ($cel % 2); + if ($next_level < 62) { + $remember[] = ['num' => 8234, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = -1; + $controlchars = true; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8238) { // RLO + // X4. With each RLO, compute the least greater odd embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to right-to-left. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + ($cel % 2) + 1; + if ($next_level < 62) { + $remember[] = ['num' => 8238, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = Ucdn::BIDI_CLASS_R; + $controlchars = true; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8237) { // LRO + // X5. With each LRO, compute the least greater even embedding level. + // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to left-to-right. + // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. + $next_level = $cel + 2 - ($cel % 2); + if ($next_level < 62) { + $remember[] = ['num' => 8237, 'cel' => $cel, 'dos' => $dos]; + $cel = $next_level; + $dos = Ucdn::BIDI_CLASS_L; + $controlchars = true; + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8236) { // PDF + // X7. With each PDF, determine the matching embedding or override code. If there was a valid matching code, restore (pop) the last remembered (pushed) embedding level and directional override. + if (count($remember)) { + $last = count($remember) - 1; + if (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) || + ($remember[$last]['num'] == 8237)) { + $match = array_pop($remember); + $cel = $match['cel']; + $dos = $match['dos']; + } + } + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8294 || $chunkOTLdata['char_data'][$i]['uni'] == 8295 || + $chunkOTLdata['char_data'][$i]['uni'] == 8296) { // LRI // RLI // FSI + // X5a. With each RLI: + // X5b. With each LRI: + // X5c. With each FSI, apply rules P2 and P3 for First Strong character + // Set the RLI/LRI/FSI embedding level to the embedding level of the last entry on the directional status stack. + if ($dos != -1) { + $chardir = $dos; + } else { + $chardir = $chunkOTLdata['char_data'][$i]['bidi_class']; + } + $chunkOTLdata['char_data'][$i]['level'] = $cel; + $chunkOTLdata['char_data'][$i]['type'] = $chardir; + $chunkOTLdata['char_data'][$i]['diid'] = $diid; + + $fsi = ''; + // X5c. With each FSI, apply rules P2 and P3 within the isolate run for First Strong character + if ($chunkOTLdata['char_data'][$i]['uni'] == 8296) { // FSI + $lvl = 0; + $nc2 = $nc; + $i2 = $i; + while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) { // while not at end of last chunk + $i2++; + if ($i2 >= count($para[$nc2][18]['char_data'])) { + $nc2++; + $i2 = 0; + } + if ($lvl > 0) { + continue; + } + if ($para[$nc2][18]['char_data'][$i2]['uni'] == 8294 || $para[$nc2][18]['char_data'][$i2]['uni'] == 8295 || $para[$nc2][18]['char_data'][$i2]['uni'] == 8296) { + $lvl++; + continue; + } + if ($para[$nc2][18]['char_data'][$i2]['uni'] == 8297) { + $lvl--; + if ($lvl < 0) { + break; + } + } + if ($para[$nc2][18]['char_data'][$i2]['bidi_class'] === Ucdn::BIDI_CLASS_L || $para[$nc2][18]['char_data'][$i2]['bidi_class'] == Ucdn::BIDI_CLASS_AL || $para[$nc2][18]['char_data'][$i2]['bidi_class'] === Ucdn::BIDI_CLASS_R) { + $fsi = $para[$nc2][18]['char_data'][$i2]['bidi_class']; + break; + } + } + // if fsi not found, fsi is same as paragraph embedding level + if (!$fsi && $fsi !== 0) { + if ($pel == 1) { + $fsi = Ucdn::BIDI_CLASS_R; + } else { + $fsi = Ucdn::BIDI_CLASS_L; + } + } + } + + if ($chunkOTLdata['char_data'][$i]['uni'] == 8294 || $fsi === Ucdn::BIDI_CLASS_L) { // LRI or FSI-L + // Compute the least even embedding level greater than the embedding level of the last entry on the directional status stack. + $next_level = $cel + 2 - ($cel % 2); + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8295 || $fsi == Ucdn::BIDI_CLASS_R || $fsi == Ucdn::BIDI_CLASS_AL) { // RLI or FSI-R + // Compute the least odd embedding level greater than the embedding level of the last entry on the directional status stack. + $next_level = $cel + ($cel % 2) + 1; + } + + + // Increment the isolate count by one, and push an entry consisting of the new embedding level, + // neutral directional override status, and true directional isolate status onto the directional status stack. + $remember[] = ['num' => $chunkOTLdata['char_data'][$i]['uni'], 'cel' => $cel, 'dos' => $dos, 'diid' => $diid]; + $cel = $next_level; + $dos = -1; + $diid = ++$dictr; // Set new direction isolate ID after incrementing direction isolate counter + + $controlchars = true; + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 8297) { // PDI + // X6a. With each PDI, perform the following steps: + // Pop the last entry from the directional status stack and decrement the isolate count by one. + while (count($remember)) { + $last = count($remember) - 1; + if (($remember[$last]['num'] == 8294) || ($remember[$last]['num'] == 8295) || ($remember[$last]['num'] == 8296)) { + $match = array_pop($remember); + $cel = $match['cel']; + $dos = $match['dos']; + $diid = $match['diid']; + break; + } // End/close any open embedding states not explicitly closed during the isolate + elseif (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) || + ($remember[$last]['num'] == 8237)) { + $match = array_pop($remember); + } + } + // In all cases, set the PDI’s level to the embedding level of the last entry on the directional status stack left after the steps above. + // NB The level assigned to an isolate initiator is always the same as that assigned to the matching PDI. + if ($dos != -1) { + $chardir = $dos; + } else { + $chardir = $chunkOTLdata['char_data'][$i]['bidi_class']; + } + $chunkOTLdata['char_data'][$i]['level'] = $cel; + $chunkOTLdata['char_data'][$i]['type'] = $chardir; + $chunkOTLdata['char_data'][$i]['diid'] = $diid; + $controlchars = true; + } elseif ($chunkOTLdata['char_data'][$i]['uni'] == 10) { // NEW LINE + // Reset to start values + $cel = $pel; + $dos = -1; + $remember = []; + } else { + // X6. For all types besides RLE, LRE, RLO, LRO, and PDF: + // a. Set the level of the current character to the current embedding level. + // b. When the directional override status is not neutral, reset the current character type to directional override status. + if ($dos != -1) { + $chardir = $dos; + } else { + $chardir = $chunkOTLdata['char_data'][$i]['bidi_class']; + if ($chardir == Ucdn::BIDI_CLASS_R || $chardir == Ucdn::BIDI_CLASS_AL) { + $strongrtl = true; + } + } + $chunkOTLdata['char_data'][$i]['level'] = $cel; + $chunkOTLdata['char_data'][$i]['type'] = $chardir; + $chunkOTLdata['char_data'][$i]['diid'] = $diid; + } + } + // X8. All explicit directional embeddings and overrides are completely terminated at the end of each paragraph. + // Paragraph separators are not included in the embedding. + // X9. Remove all RLE, LRE, RLO, LRO, and PDF codes. + if ($controlchars) { + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xaa"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xab"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xac"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xad"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xae"); + preg_replace("/\x{202a}-\x{202e}/u", '', $para[$nc][0]); + } + } + + // Remove any blank chunks made by removing directional codes + $numchunks = count($para); + for ($nc = ($numchunks - 1); $nc >= 0; $nc--) { + if (count($para[$nc][18]['char_data']) == 0) { + array_splice($para, $nc, 1); + } + } + if ($dir != 'rtl' && !$strongrtl && !$controlchars) { + return; + } + + $numchunks = count($para); + + // X10. Determine the start-of-sequence (sor) and end-of-sequence (eor) types, either L or R, for each isolating run sequence. These depend on the higher of the two levels on either side of the sequence boundary: + // For sor, compare the level of the first character in the sequence with the level of the character preceding it in the paragraph or if there is none, with the paragraph embedding level. + // For eor, compare the level of the last character in the sequence with the level of the character following it in the paragraph or if there is none, with the paragraph embedding level. + // If the higher level is odd, the sor or eor is R; otherwise, it is L. + + for ($ir = 0; $ir <= $dictr; $ir++) { + $prelevel = $pel; + $postlevel = $pel; + $firstchar = true; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + $right = $postlevel; + $nc2 = $nc; + $i2 = $i; + while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) { // while not at end of last chunk + $i2++; + if ($i2 >= count($para[$nc2][18]['char_data'])) { + $nc2++; + $i2 = 0; + } + + if (isset($para[$nc2][18]['char_data'][$i2]['diid']) && $para[$nc2][18]['char_data'][$i2]['diid'] == $ir) { + $right = $para[$nc2][18]['char_data'][$i2]['level']; + break; + } + } + + $level = $chardata[$i]['level']; + if ($firstchar || $level != $prelevel) { + $chardata[$i]['sor'] = max($prelevel, $level) % 2 ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + } + if (($nc == ($numchunks - 1) && $i == ($numchars - 1)) || $level != $right) { + $chardata[$i]['eor'] = max($right, $level) % 2 ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + } + $prelevel = $level; + $firstchar = false; + } + } + } + + + // 3.3.3 Resolving Weak Types + // Weak types are now resolved one level run at a time. At level run boundaries where the type of the character on the other side of the boundary is required, the type assigned to sor or eor is used. + // Nonspacing marks are now resolved based on the previous characters. + // W1. Examine each nonspacing mark (NSM) in the level run, and change the type of the NSM to the type of the previous character. If the NSM is at the start of the level run, it will get the type of sor. + for ($ir = 0; $ir <= $dictr; $ir++) { + $prevtype = 0; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_NSM) { + if (isset($chardata[$i]['sor'])) { + $chardata[$i]['type'] = $chardata[$i]['sor']; + } else { + $chardata[$i]['type'] = $prevtype; + } + } + $prevtype = $chardata[$i]['type']; + } + } + } + + // W2. Search backward from each instance of a European number until the first strong type (R, L, AL or sor) is found. If an AL is found, change the type of the European number to Arabic number. + for ($ir = 0; $ir <= $dictr; $ir++) { + $laststrongtype = -1; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + if (isset($chardata[$i]['sor'])) { + $laststrongtype = $chardata[$i]['sor']; + } + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN && $laststrongtype == Ucdn::BIDI_CLASS_AL) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_AN; + } + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_L || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_R || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_AL) { + $laststrongtype = $chardata[$i]['type']; + } + } + } + } + + + // W3. Change all ALs to R. + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (isset($chardata[$i]['type']) && $chardata[$i]['type'] == Ucdn::BIDI_CLASS_AL) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_R; + } + } + } + + + // W4. A single European separator between two European numbers changes to a European number. A single common separator between two numbers of the same type changes to that type. + for ($ir = 0; $ir <= $dictr; $ir++) { + $prevtype = -1; + $nexttype = -1; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + // Get next type + $nexttype = -1; + $nc2 = $nc; + $i2 = $i; + while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) { // while not at end of last chunk + $i2++; + if ($i2 >= count($para[$nc2][18]['char_data'])) { + $nc2++; + $i2 = 0; + } + + if (isset($para[$nc2][18]['char_data'][$i2]['diid']) && $para[$nc2][18]['char_data'][$i2]['diid'] == $ir) { + $nexttype = $para[$nc2][18]['char_data'][$i2]['type']; + break; + } + } + + if (!isset($chardata[$i]['sor']) && !isset($chardata[$i]['eor'])) { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ES && $prevtype == Ucdn::BIDI_CLASS_EN && $nexttype == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } elseif ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS && $prevtype == Ucdn::BIDI_CLASS_EN && $nexttype == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } elseif ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS && $prevtype == Ucdn::BIDI_CLASS_AN && $nexttype == Ucdn::BIDI_CLASS_AN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_AN; + } + } + $prevtype = $chardata[$i]['type']; + } + } + } + + // W5. A sequence of European terminators adjacent to European numbers changes to all European numbers. + for ($ir = 0; $ir <= $dictr; $ir++) { + $prevtype = -1; + $nexttype = -1; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + if (isset($chardata[$i]['sor'])) { + $prevtype = $chardata[$i]['sor']; + } + + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ET) { + if ($prevtype == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + } elseif (!isset($chardata[$i]['eor'])) { + $nexttype = -1; + $nc2 = $nc; + $i2 = $i; + while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) { // while not at end of last chunk + $i2++; + if ($i2 >= count($para[$nc2][18]['char_data'])) { + $nc2++; + $i2 = 0; + } + if (!isset($para[$nc2][18]['char_data'][$i2]['diid']) || $para[$nc2][18]['char_data'][$i2]['diid'] != $ir) { + continue; + } + $nexttype = $para[$nc2][18]['char_data'][$i2]['type']; + if (isset($para[$nc2][18]['char_data'][$i2]['sor'])) { + break; + } + if ($nexttype == Ucdn::BIDI_CLASS_EN) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_EN; + break; + } elseif ($nexttype != Ucdn::BIDI_CLASS_ET) { + break; + } + } + } + } + $prevtype = $chardata[$i]['type']; + } + } + } + + // W6. Otherwise, separators and terminators change to Other Neutral. + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (isset($chardata[$i]['type']) && (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ET) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ES) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_CS))) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_ON; + } + } + } + + //W7. Search backward from each instance of a European number until the first strong type (R, L, or sor) is found. If an L is found, then change the type of the European number to L. + for ($ir = 0; $ir <= $dictr; $ir++) { + $laststrongtype = -1; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + if (isset($chardata[$i]['sor'])) { + $laststrongtype = $chardata[$i]['sor']; + } + if (isset($chardata[$i]['type']) && $chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN && $laststrongtype == Ucdn::BIDI_CLASS_L) { + $chardata[$i]['type'] = Ucdn::BIDI_CLASS_L; + } + if (isset($chardata[$i]['type']) && ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_L || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_R || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_AL)) { + $laststrongtype = $chardata[$i]['type']; + } + } + } + } + + // N1. A sequence of neutrals takes the direction of the surrounding strong text if the text on both sides has the same direction. European and Arabic numbers act as if they were R in terms of their influence on neutrals. Start-of-level-run (sor) and end-of-level-run (eor) are used at level run boundaries. + for ($ir = 0; $ir <= $dictr; $ir++) { + $laststrongtype = -1; + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) { + continue; + } // Ignore characters in a different isolate run + if (isset($chardata[$i]['sor'])) { + $laststrongtype = $chardata[$i]['sor']; + } + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ON || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_WS) { + $left = -1; + // LEFT + if ($laststrongtype == Ucdn::BIDI_CLASS_R || $laststrongtype == Ucdn::BIDI_CLASS_EN || $laststrongtype == Ucdn::BIDI_CLASS_AN) { + $left = Ucdn::BIDI_CLASS_R; + } elseif ($laststrongtype == Ucdn::BIDI_CLASS_L) { + $left = Ucdn::BIDI_CLASS_L; + } + // RIGHT + $right = -1; + // move to the right of any following neutrals OR hit a run boundary + + if (isset($chardata[$i]['eor'])) { + $right = $chardata[$i]['eor']; + } else { + $nexttype = -1; + $nc2 = $nc; + $i2 = $i; + while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) { // while not at end of last chunk + $i2++; + if ($i2 >= count($para[$nc2][18]['char_data'])) { + $nc2++; + $i2 = 0; + } + if (!isset($para[$nc2][18]['char_data'][$i2]['diid']) || $para[$nc2][18]['char_data'][$i2]['diid'] != $ir) { + continue; + } + $nexttype = $para[$nc2][18]['char_data'][$i2]['type']; + if ($nexttype == Ucdn::BIDI_CLASS_R || $nexttype == Ucdn::BIDI_CLASS_EN || $nexttype == Ucdn::BIDI_CLASS_AN) { + $right = Ucdn::BIDI_CLASS_R; + break; + } elseif ($nexttype == Ucdn::BIDI_CLASS_L) { + $right = Ucdn::BIDI_CLASS_L; + break; + } elseif (isset($para[$nc2][18]['char_data'][$i2]['eor'])) { + $right = $para[$nc2][18]['char_data'][$i2]['eor']; + break; + } + } + } + + if ($left > -1 && $left == $right) { + $chardata[$i]['orig_type'] = $chardata[$i]['type']; // Need to store the original 'WS' for reference in L1 below + $chardata[$i]['type'] = $left; + } + } elseif ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_L || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_R || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_AN) { + $laststrongtype = $chardata[$i]['type']; + } + } + } + } + + // N2. Any remaining neutrals take the embedding direction + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (isset($chardata[$i]['type']) && ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_ON || $chardata[$i]['type'] == Ucdn::BIDI_CLASS_WS)) { + $chardata[$i]['orig_type'] = $chardata[$i]['type']; // Need to store the original 'WS' for reference in L1 below + $chardata[$i]['type'] = ($chardata[$i]['level'] % 2) ? Ucdn::BIDI_CLASS_R : Ucdn::BIDI_CLASS_L; + } + } + } + + // I1. For all characters with an even (left-to-right) embedding direction, those of type R go up one level and those of type AN or EN go up two levels. + // I2. For all characters with an odd (right-to-left) embedding direction, those of type L, EN or AN go up one level. + for ($nc = 0; $nc < $numchunks; $nc++) { + $chardata = & $para[$nc][18]['char_data']; + $numchars = count($chardata); + for ($i = 0; $i < $numchars; ++$i) { + if (isset($chardata[$i]['level'])) { + $odd = $chardata[$i]['level'] % 2; + if ($odd) { + if (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_L) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_AN) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN)) { + $chardata[$i]['level'] += 1; + } + } else { + if ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_R) { + $chardata[$i]['level'] += 1; + } elseif (($chardata[$i]['type'] == Ucdn::BIDI_CLASS_AN) || ($chardata[$i]['type'] == Ucdn::BIDI_CLASS_EN)) { + $chardata[$i]['level'] += 2; + } + } + } + } + } + + // Remove Isolate formatters + $numchunks = count($para); + if ($controlchars) { + for ($nc = 0; $nc < $numchunks; $nc++) { + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa6"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa7"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa8"); + $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa9"); + preg_replace("/\x{2066}-\x{2069}/u", '', $para[$nc][0]); + } + // Remove any blank chunks made by removing directional codes + for ($nc = ($numchunks - 1); $nc >= 0; $nc--) { + if (count($para[$nc][18]['char_data']) == 0) { + array_splice($para, $nc, 1); + } + } + } + } + + /** + * Reorder, once divided into lines + */ + public function bidiReorder(&$chunkorder, &$content, &$cOTLdata, $blockdir) + { + $bidiData = []; + + // First combine into one array (and get the highest level in use) + $numchunks = count($content); + $maxlevel = 0; + + for ($nc = 0; $nc < $numchunks; $nc++) { + + $numchars = isset($cOTLdata[$nc]['char_data']) ? count($cOTLdata[$nc]['char_data']) : 0; + for ($i = 0; $i < $numchars; ++$i) { + + $carac = [ + 'level' => 0, + ]; + + if (isset($cOTLdata[$nc]['GPOSinfo'][$i])) { + $carac['GPOSinfo'] = $cOTLdata[$nc]['GPOSinfo'][$i]; + } + + $carac['uni'] = $cOTLdata[$nc]['char_data'][$i]['uni']; + + if (isset($cOTLdata[$nc]['char_data'][$i]['type'])) { + $carac['type'] = $cOTLdata[$nc]['char_data'][$i]['type']; + } + + if (isset($cOTLdata[$nc]['char_data'][$i]['level'])) { + $carac['level'] = $cOTLdata[$nc]['char_data'][$i]['level']; + } + + if (isset($cOTLdata[$nc]['char_data'][$i]['orig_type'])) { + $carac['orig_type'] = $cOTLdata[$nc]['char_data'][$i]['orig_type']; + } + + $carac['group'] = $cOTLdata[$nc]['group'][$i]; + $carac['chunkid'] = $chunkorder[$nc]; // gives font id and/or object ID + + $maxlevel = max((isset($carac['level']) ? $carac['level'] : 0), $maxlevel); + $bidiData[] = $carac; + } + } + if ($maxlevel === 0) { + return; + } + + $numchars = count($bidiData); + + // L1. On each line, reset the embedding level of the following characters to the paragraph embedding level: + // 1. Segment separators (Tab) 'S', + // 2. Paragraph separators 'B', + // 3. Any sequence of whitespace characters 'WS' preceding a segment separator or paragraph separator, and + // 4. Any sequence of whitespace characters 'WS' at the end of the line. + // The types of characters used here are the original types, not those modified by the previous phase cf N1 and N2******* + // Because a Paragraph Separator breaks lines, there will be at most one per line, at the end of that line. + // Set the initial paragraph embedding level + if ($blockdir === 'rtl') { + $pel = 1; + } else { + $pel = 0; + } + + for ($i = ($numchars - 1); $i > 0; $i--) { + if ($bidiData[$i]['type'] == Ucdn::BIDI_CLASS_WS || (isset($bidiData[$i]['orig_type']) && $bidiData[$i]['orig_type'] == Ucdn::BIDI_CLASS_WS)) { + $bidiData[$i]['level'] = $pel; + } else { + break; + } + } + + // L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher. + for ($j = $maxlevel; $j > 0; $j--) { + $ordarray = []; + $revarr = []; + $onlevel = false; + for ($i = 0; $i < $numchars; ++$i) { + + if ($bidiData[$i]['level'] >= $j) { + $onlevel = true; + // L4. A character is depicted by a mirrored glyph if and only if (a) the resolved directionality of that character is R, and (b) the Bidi_Mirrored property value of that character is true. + if (isset(Ucdn::$mirror_pairs[$bidiData[$i]['uni']]) && $bidiData[$i]['type'] == Ucdn::BIDI_CLASS_R) { + $bidiData[$i]['uni'] = Ucdn::$mirror_pairs[$bidiData[$i]['uni']]; + } + + $revarr[] = $bidiData[$i]; + + } else { + + if ($onlevel) { + $revarr = array_reverse($revarr); + $ordarray = array_merge($ordarray, $revarr); + $revarr = []; + $onlevel = false; + } + + $ordarray[] = $bidiData[$i]; + } + } + + if ($onlevel) { + $revarr = array_reverse($revarr); + $ordarray = array_merge($ordarray, $revarr); + } + + $bidiData = $ordarray; + } + + $content = []; + $cOTLdata = []; + $chunkorder = []; + + $nc = -1; // New chunk order ID + $chunkid = -1; + + foreach ($bidiData as $carac) { + if ($carac['chunkid'] != $chunkid) { + $nc++; + $chunkorder[$nc] = $carac['chunkid']; + $cctr = 0; + $content[$nc] = ''; + $cOTLdata[$nc]['group'] = ''; + } + if ($carac['uni'] != 0xFFFC) { // Object replacement character (65532) + $content[$nc] .= UtfString::code2utf($carac['uni']); + $cOTLdata[$nc]['group'] .= $carac['group']; + if (!empty($carac['GPOSinfo'])) { + if (isset($carac['GPOSinfo'])) { + $cOTLdata[$nc]['GPOSinfo'][$cctr] = $carac['GPOSinfo']; + } + $cOTLdata[$nc]['GPOSinfo'][$cctr]['wDir'] = ($carac['level'] % 2) ? 'RTL' : 'LTR'; + } + } + $chunkid = $carac['chunkid']; + $cctr++; + } + } + + public function splitOTLdata(&$cOTLdata, $OTLcutoffpos, $OTLrestartpos = '') + { + if (!$OTLrestartpos) { + $OTLrestartpos = $OTLcutoffpos; + } + $newOTLdata = ['GPOSinfo' => [], 'char_data' => []]; + $newOTLdata['group'] = substr($cOTLdata['group'], $OTLrestartpos); + $cOTLdata['group'] = substr($cOTLdata['group'], 0, $OTLcutoffpos); + + if (isset($cOTLdata['GPOSinfo']) && $cOTLdata['GPOSinfo']) { + foreach ($cOTLdata['GPOSinfo'] as $k => $val) { + if ($k >= $OTLrestartpos) { + $newOTLdata['GPOSinfo'][($k - $OTLrestartpos)] = $val; + } + if ($k >= $OTLcutoffpos) { + unset($cOTLdata['GPOSinfo'][$k]); + //$cOTLdata['GPOSinfo'][$k] = array(); + } + } + } + if (isset($cOTLdata['char_data'])) { + $newOTLdata['char_data'] = array_slice($cOTLdata['char_data'], $OTLrestartpos); + array_splice($cOTLdata['char_data'], $OTLcutoffpos); + } + + // Not necessary - easier to debug + if (isset($cOTLdata['GPOSinfo'])) { + ksort($cOTLdata['GPOSinfo']); + } + if (isset($newOTLdata['GPOSinfo'])) { + ksort($newOTLdata['GPOSinfo']); + } + + return $newOTLdata; + } + + public function sliceOTLdata($OTLdata, $pos, $len) + { + $newOTLdata = ['GPOSinfo' => [], 'char_data' => []]; + $newOTLdata['group'] = substr($OTLdata['group'], $pos, $len); + + if ($OTLdata['GPOSinfo']) { + foreach ($OTLdata['GPOSinfo'] as $k => $val) { + if ($k >= $pos && $k < ($pos + $len)) { + $newOTLdata['GPOSinfo'][($k - $pos)] = $val; + } + } + } + + if (isset($OTLdata['char_data'])) { + $newOTLdata['char_data'] = array_slice($OTLdata['char_data'], $pos, $len); + } + + // Not necessary - easier to debug + if ($newOTLdata['GPOSinfo']) { + ksort($newOTLdata['GPOSinfo']); + } + + return $newOTLdata; + } + + /** + * Remove one or more occurrences of $char (single character) from $txt and adjust OTLdata + */ + public function removeChar(&$txt, &$cOTLdata, $char) + { + while (mb_strpos($txt, $char, 0, $this->mpdf->mb_enc) !== false) { + $pos = mb_strpos($txt, $char, 0, $this->mpdf->mb_enc); + $newGPOSinfo = []; + $cOTLdata['group'] = substr_replace($cOTLdata['group'], '', $pos, 1); + if ($cOTLdata['GPOSinfo']) { + foreach ($cOTLdata['GPOSinfo'] as $k => $val) { + if ($k > $pos) { + $newGPOSinfo[($k - 1)] = $val; + } elseif ($k != $pos) { + $newGPOSinfo[$k] = $val; + } + } + $cOTLdata['GPOSinfo'] = $newGPOSinfo; + } + if (isset($cOTLdata['char_data'])) { + array_splice($cOTLdata['char_data'], $pos, 1); + } + + $txt = preg_replace("/" . $char . "/", '', $txt, 1); + } + } + + /** + * Remove one or more occurrences of $char (single character) from $txt and adjust OTLdata + */ + public function replaceSpace(&$txt, &$cOTLdata) + { + $char = chr(194) . chr(160); // NBSP + while (mb_strpos($txt, $char, 0, $this->mpdf->mb_enc) !== false) { + $pos = mb_strpos($txt, $char, 0, $this->mpdf->mb_enc); + if ($cOTLdata['char_data'][$pos]['uni'] == 160) { + $cOTLdata['char_data'][$pos]['uni'] = 32; + } + $txt = preg_replace("/" . $char . "/", ' ', $txt, 1); + } + } + + public function trimOTLdata(&$cOTLdata, $Left = true, $Right = true) + { + $len = (!is_array($cOTLdata) || $cOTLdata['char_data'] === null) ? 0 : count($cOTLdata['char_data']); + $nLeft = 0; + $nRight = 0; + for ($i = 0; $i < $len; $i++) { + if ($cOTLdata['char_data'][$i]['uni'] == 32 || $cOTLdata['char_data'][$i]['uni'] == 12288) { + $nLeft++; + } // 12288 = 0x3000 = CJK space + else { + break; + } + } + for ($i = ($len - 1); $i >= 0; $i--) { + if ($cOTLdata['char_data'][$i]['uni'] == 32 || $cOTLdata['char_data'][$i]['uni'] == 12288) { + $nRight++; + } // 12288 = 0x3000 = CJK space + else { + break; + } + } + + // Trim Right + if ($Right && $nRight) { + $cOTLdata['group'] = substr($cOTLdata['group'], 0, strlen($cOTLdata['group']) - $nRight); + if ($cOTLdata['GPOSinfo']) { + foreach ($cOTLdata['GPOSinfo'] as $k => $val) { + if ($k >= $len - $nRight) { + unset($cOTLdata['GPOSinfo'][$k]); + } + } + } + if (isset($cOTLdata['char_data'])) { + for ($i = 0; $i < $nRight; $i++) { + array_pop($cOTLdata['char_data']); + } + } + } + // Trim Left + if ($Left && $nLeft) { + $cOTLdata['group'] = substr($cOTLdata['group'], $nLeft); + if ($cOTLdata['GPOSinfo']) { + $newPOSinfo = []; + foreach ($cOTLdata['GPOSinfo'] as $k => $val) { + if ($k >= $nLeft) { + $newPOSinfo[$k - $nLeft] = $cOTLdata['GPOSinfo'][$k]; + } + } + $cOTLdata['GPOSinfo'] = $newPOSinfo; + } + if (isset($cOTLdata['char_data'])) { + for ($i = 0; $i < $nLeft; $i++) { + array_shift($cOTLdata['char_data']); + } + } + } + } + + //////////////////////////////////////////////////////////////// + ////////// GENERAL OTL FUNCTIONS ///////////////// + //////////////////////////////////////////////////////////////// + + private function glyphToChar($gid) + { + return (ord($this->glyphIDtoUni[$gid * 3]) << 16) + (ord($this->glyphIDtoUni[$gid * 3 + 1]) << 8) + ord($this->glyphIDtoUni[$gid * 3 + 2]); + } + + private function unicode_hex($unicode_dec) + { + return (str_pad(strtoupper(dechex($unicode_dec)), 5, '0', STR_PAD_LEFT)); + } + + private function seek($pos) + { + $this->_pos = $pos; + } + + private function skip($delta) + { + $this->_pos += $delta; + } + + private function read_short() + { + $a = (ord($this->ttfOTLdata[$this->_pos]) << 8) + ord($this->ttfOTLdata[$this->_pos + 1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + $this->_pos += 2; + return $a; + } + + private function read_ushort() + { + $a = (ord($this->ttfOTLdata[$this->_pos]) << 8) + ord($this->ttfOTLdata[$this->_pos + 1]); + $this->_pos += 2; + return $a; + } + + private function _getCoverageGID() + { + // Called from Lookup Type 1, Format 1 - returns glyphIDs rather than hexstrings + // Need to do this separately to cache separately + // Otherwise the same as fn below _getCoverage + $offset = $this->_pos; + if (isset($this->LuDataCache[$this->fontkey]['GID'][$offset])) { + $g = $this->LuDataCache[$this->fontkey]['GID'][$offset]; + } else { + $g = []; + $CoverageFormat = $this->read_ushort(); + if ($CoverageFormat == 1) { + $CoverageGlyphCount = $this->read_ushort(); + for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) { + $glyphID = $this->read_ushort(); + $g[] = $glyphID; + } + } + if ($CoverageFormat == 2) { + $RangeCount = $this->read_ushort(); + for ($r = 0; $r < $RangeCount; $r++) { + $start = $this->read_ushort(); + $end = $this->read_ushort(); + $StartCoverageIndex = $this->read_ushort(); // n/a + for ($glyphID = $start; $glyphID <= $end; $glyphID++) { + $g[] = $glyphID; + } + } + } + $this->LuDataCache[$this->fontkey]['GID'][$offset] = $g; + } + return $g; + } + + private function _getCoverage() + { + $offset = $this->_pos; + if (isset($this->LuDataCache[$this->fontkey][$offset])) { + $g = $this->LuDataCache[$this->fontkey][$offset]; + } else { + $g = []; + $CoverageFormat = $this->read_ushort(); + if ($CoverageFormat == 1) { + $CoverageGlyphCount = $this->read_ushort(); + for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) { + $glyphID = $this->read_ushort(); + $g[] = $this->unicode_hex($this->glyphToChar($glyphID)); + } + } + if ($CoverageFormat == 2) { + $RangeCount = $this->read_ushort(); + for ($r = 0; $r < $RangeCount; $r++) { + $start = $this->read_ushort(); + $end = $this->read_ushort(); + $StartCoverageIndex = $this->read_ushort(); // n/a + for ($glyphID = $start; $glyphID <= $end; $glyphID++) { + $g[] = $this->unicode_hex($this->glyphToChar($glyphID)); + } + } + } + $this->LuDataCache[$this->fontkey][$offset] = $g; + } + return $g; + } + + private function _getClasses($offset) + { + if (isset($this->LuDataCache[$this->fontkey][$offset])) { + $GlyphByClass = $this->LuDataCache[$this->fontkey][$offset]; + } else { + $this->seek($offset); + $ClassFormat = $this->read_ushort(); + $GlyphByClass = []; + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $startGlyphID = $StartGlyph + $i; + $endGlyphID = $StartGlyph + $i; + $class = $this->read_ushort(); + // Note: Font FreeSerif , tag "blws" + // $BacktrackClasses[0] is defined ? a mistake in the font ??? + // Let's ignore for now + if ($class > 0) { + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if ($this->glyphToChar($g)) { + $GlyphByClass[$class][$this->glyphToChar($g)] = 1; + } + } + } + } + } elseif ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $startGlyphID = $this->read_ushort(); + $endGlyphID = $this->read_ushort(); + $class = $this->read_ushort(); + // Note: Font FreeSerif , tag "blws" + // $BacktrackClasses[0] is defined ? a mistake in the font ??? + // Let's ignore for now + if ($class > 0) { + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if ($this->glyphToChar($g)) { + $GlyphByClass[$class][$this->glyphToChar($g)] = 1; + } + } + } + } + } + $this->LuDataCache[$this->fontkey][$offset] = $GlyphByClass; + } + return $GlyphByClass; + } + + private function _getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $shaper, $useOTL, $mode) + { + // ScriptLang is the array of available script/lang tags supported by the font + // $scriptblock is the (number/code) for the script of the actual text string based on Unicode properties (Ucdn::$uni_scriptblock) + // $scripttag is the default tag derived from $scriptblock + /* + http://www.microsoft.com/typography/otspec/ttoreg.htm + http://www.microsoft.com/typography/otspec/scripttags.htm + + Values for useOTL + + Bit dn hn Value + 1 1 0x0001 GSUB/GPOS - Latin scripts + 2 2 0x0002 GSUB/GPOS - Cyrillic scripts + 3 4 0x0004 GSUB/GPOS - Greek scripts + 4 8 0x0008 GSUB/GPOS - CJK scripts (excluding Hangul-Jamo) + 5 16 0x0010 (Reserved) + 6 32 0x0020 (Reserved) + 7 64 0x0040 (Reserved) + 8 128 0x0080 GSUB/GPOS - All other scripts (including all RTL scripts, complex scripts with shapers etc) + + NB If change for RTL - cf. function magic_reverse_dir in mpdf.php to update + + */ + + + if ($scriptblock == Ucdn::SCRIPT_LATIN) { + if (!($useOTL & 0x01)) { + return ['', false]; + } + } elseif ($scriptblock == Ucdn::SCRIPT_CYRILLIC) { + if (!($useOTL & 0x02)) { + return ['', false]; + } + } elseif ($scriptblock == Ucdn::SCRIPT_GREEK) { + if (!($useOTL & 0x04)) { + return ['', false]; + } + } elseif ($scriptblock >= Ucdn::SCRIPT_HIRAGANA && $scriptblock <= Ucdn::SCRIPT_YI) { + if (!($useOTL & 0x08)) { + return ['', false]; + } + } else { + if (!($useOTL & 0x80)) { + return ['', false]; + } + } + + // If availabletags includes scripttag - choose + if (isset($ScriptLang[$scripttag])) { + return [$scripttag, false]; + } + + // If INDIC (or Myanmar) and available tag not includes new version, check if includes old version & choose old version + if ($shaper) { + switch ($scripttag) { + case 'bng2': + if (isset($ScriptLang['beng'])) { + return ['beng', true]; + } + // fallthrough + case 'dev2': + if (isset($ScriptLang['deva'])) { + return ['deva', true]; + } + // fallthrough + case 'gjr2': + if (isset($ScriptLang['gujr'])) { + return ['gujr', true]; + } + // fallthrough + case 'gur2': + if (isset($ScriptLang['guru'])) { + return ['guru', true]; + } + // fallthrough + case 'knd2': + if (isset($ScriptLang['knda'])) { + return ['knda', true]; + } + // fallthrough + case 'mlm2': + if (isset($ScriptLang['mlym'])) { + return ['mlym', true]; + } + // fallthrough + case 'ory2': + if (isset($ScriptLang['orya'])) { + return ['orya', true]; + } + // fallthrough + case 'tml2': + if (isset($ScriptLang['taml'])) { + return ['taml', true]; + } + // fallthrough + case 'tel2': + if (isset($ScriptLang['telu'])) { + return ['telu', true]; + } + // fallthrough + case 'mym2': + if (isset($ScriptLang['mymr'])) { + return ['mymr', true]; + } + } + } + + // choose DFLT if present + if (isset($ScriptLang['DFLT'])) { + return ['DFLT', false]; + } + // else choose dflt if present + if (isset($ScriptLang['dflt'])) { + return ['dflt', false]; + } + // else return no scriptTag + if (isset($ScriptLang['latn'])) { + return ['latn', false]; + } + // else return no scriptTag + return ['', false]; + } + + // LangSys tags + private function _getOTLLangTag($ietf, $available) + { + // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + // http://www.microsoft.com/typography/otspec/languagetags.htm + // IETF tag = e.g. en-US, und-Arab, sr-Cyrl cf. class LangToFont + if ($available == '') { + return ''; + } + + $tags = $ietf + ? preg_split('/-/', $ietf) + : []; + + $lang = ''; + $country = ''; + $script = ''; + + $lang = isset($tags[0]) + ? strtolower($tags[0]) + : ''; + + if (isset($tags[1]) && $tags[1]) { + if (strlen($tags[1]) == 2) { + $country = strtolower($tags[1]); + } + } + + if (isset($tags[2]) && $tags[2]) { + $country = strtolower($tags[2]); + } + + if ($lang != '' && isset(Ucdn::$ot_languages[$lang])) { + $langsys = Ucdn::$ot_languages[$lang]; + } elseif ($lang != '' && $country != '' && isset(Ucdn::$ot_languages[$lang . '' . $country])) { + $langsys = Ucdn::$ot_languages[$lang . '' . $country]; + } else { + $langsys = "DFLT"; + } + + if (strpos($available, $langsys) === false) { + if (strpos($available, "DFLT") !== false) { + return "DFLT"; + } else { + return ''; + } + } + + return $langsys; + } + + private function _dumpproc($GPOSSUB, $lookupID, $subtable, $Type, $Format, $ptr, $currGlyph, $level) + { + echo '<div style="padding-left: ' . ($level * 2) . 'em;">'; + echo $GPOSSUB . ' LookupID #' . $lookupID . ' Subtable#' . $subtable . ' Type: ' . $Type . ' Format: ' . $Format . '<br />'; + echo '<div style="font-family:monospace">'; + echo 'Glyph position: ' . $ptr . ' Current Glyph: ' . $currGlyph . '<br />'; + + for ($i = 0; $i < count($this->OTLdata); $i++) { + if ($i == $ptr) { + echo '<b>'; + } + echo $this->OTLdata[$i]['hex'] . ' '; + if ($i == $ptr) { + echo '</b>'; + } + } + echo '<br />'; + + for ($i = 0; $i < count($this->OTLdata); $i++) { + if ($i == $ptr) { + echo '<b>'; + } + echo str_pad($this->OTLdata[$i]['uni'], 5) . ' '; + if ($i == $ptr) { + echo '</b>'; + } + } + echo '<br />'; + + if ($GPOSSUB == 'GPOS') { + for ($i = 0; $i < count($this->OTLdata); $i++) { + if (!empty($this->OTLdata[$i]['GPOSinfo'])) { + echo $this->OTLdata[$i]['hex'] . ' &#x' . $this->OTLdata[$i]['hex'] . '; '; + print_r($this->OTLdata[$i]['GPOSinfo']); + echo ' '; + } + } + } + + echo '</div>'; + echo '</div>'; + } +} diff --git a/src/vendor/mpdf/mpdf/src/OtlDump.php b/src/vendor/mpdf/mpdf/src/OtlDump.php new file mode 100644 index 000000000..30d0ecfdd --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/OtlDump.php @@ -0,0 +1,4369 @@ +<?php + +namespace Mpdf; + +// Define the value used in the "head" table of a created TTF file +// 0x74727565 "true" for Mac +// 0x00010000 for Windows +// Either seems to work for a font embedded in a PDF file +// when read by Adobe Reader on a Windows PC(!) +use Mpdf\Fonts\GlyphOperator; + +if (!defined('_TTF_MAC_HEADER')) { + define("_TTF_MAC_HEADER", false); +} + +// Recalculate correct metadata/profiles when making subset fonts (not SIP/SMP) +// e.g. xMin, xMax, maxNContours +if (!defined('_RECALC_PROFILE')) { + define("_RECALC_PROFILE", false); +} + +// mPDF 5.7.1 +if (!function_exists('Mpdf\unicode_hex')) { + function unicode_hex($unicode_dec) + { + return (sprintf("%05s", strtoupper(dechex($unicode_dec)))); + } +} + +class OtlDump +{ + + var $GPOSFeatures; // mPDF 5.7.1 + + var $GPOSLookups; // mPDF 5.7.1 + + var $GPOSScriptLang; // mPDF 5.7.1 + + var $ignoreStrings; // mPDF 5.7.1 + + var $MarkAttachmentType; // mPDF 5.7.1 + + var $MarkGlyphSets; // mPDF 7.5.1 + + var $GlyphClassMarks; // mPDF 5.7.1 + + var $GlyphClassLigatures; // mPDF 5.7.1 + + var $GlyphClassBases; // mPDF 5.7.1 + + var $GlyphClassComponents; // mPDF 5.7.1 + + var $GSUBScriptLang; // mPDF 5.7.1 + + var $rtlPUAstr; // mPDF 5.7.1 + + var $rtlPUAarr; // mPDF 5.7.1 + + var $fontkey; // mPDF 5.7.1 + + var $useOTL; // mPDF 5.7.1 + + var $panose; + + var $maxUni; + + var $sFamilyClass; + + var $sFamilySubClass; + + var $sipset; + + var $smpset; + + var $_pos; + + var $numTables; + + var $searchRange; + + var $entrySelector; + + var $rangeShift; + + var $tables; + + var $otables; + + var $filename; + + var $fh; + + var $glyphPos; + + var $charToGlyph; + + var $ascent; + + var $descent; + + var $name; + + var $familyName; + + var $styleName; + + var $fullName; + + var $uniqueFontID; + + var $unitsPerEm; + + var $bbox; + + var $capHeight; + + var $stemV; + + var $italicAngle; + + var $flags; + + var $underlinePosition; + + var $underlineThickness; + + var $charWidths; + + var $defaultWidth; + + var $maxStrLenRead; + + var $numTTCFonts; + + var $TTCFonts; + + var $maxUniChar; + + var $kerninfo; + + var $mode; + + var $glyphToChar; + + var $fontRevision; + + var $glyphdata; + + var $glyphIDtoUn; + + var $restrictedUse; + + var $GSUBFeatures; + + var $GSUBLookups; + + var $glyphIDtoUni; + + var $GSLuCoverage; + + var $version; + + private $mpdf; + + public function __construct(Mpdf $mpdf) + { + $this->mpdf = $mpdf; + $this->maxStrLenRead = 200000; // Maximum size of glyf table to read in as string (otherwise reads each glyph from file) + } + + function getMetrics($file, $fontkey, $TTCfontID = 0, $debug = false, $BMPonly = false, $kerninfo = false, $useOTL = 0, $mode = null) + { + // mPDF 5.7.1 + $this->mode = $mode; + $this->useOTL = $useOTL; // mPDF 5.7.1 + $this->fontkey = $fontkey; // mPDF 5.7.1 + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file "%s"', $file)); + } + + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->kerninfo = []; + $this->ascent = 0; + $this->descent = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->version = $version = $this->read_ulong(); + $this->panose = []; + + if ($version == 0x4F54544F) { + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); + } + + if ($version == 0x74746366 && !$TTCfontID) { + throw new \Mpdf\Exception\FontException("TTCfontID for a TrueType Collection has to be defined in ttfontdata configuration key (" . $file . ")"); + } + + if (!in_array($version, [0x00010000, 0x74727565]) && !$TTCfontID) { + throw new \Mpdf\Exception\FontException("Not a TrueType font: version=" . $version); + } + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000])) { + throw new \Mpdf\Exception\FontException("Error parsing TrueType Collection: version=" . $version . " - " . $file); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + $this->readTableDirectory($debug); + $this->extractInfo($debug, $BMPonly, $kerninfo, $useOTL); + fclose($this->fh); + } + + function readTableDirectory($debug = false) + { + $this->numTables = $this->read_ushort(); + $this->searchRange = $this->read_ushort(); + $this->entrySelector = $this->read_ushort(); + $this->rangeShift = $this->read_ushort(); + $this->tables = []; + for ($i = 0; $i < $this->numTables; $i++) { + $record = []; + $record['tag'] = $this->read_tag(); + $record['checksum'] = [$this->read_ushort(), $this->read_ushort()]; + $record['offset'] = $this->read_ulong(); + $record['length'] = $this->read_ulong(); + $this->tables[$record['tag']] = $record; + } + if ($debug) { + $this->checksumTables(); + } + } + + function checksumTables() + { + // Check the checksums for all tables + foreach ($this->tables as $t) { + if ($t['length'] > 0 && $t['length'] < $this->maxStrLenRead) { // 1.02 + $table = $this->get_chunk($t['offset'], $t['length']); + $checksum = $this->calcChecksum($table); + if ($t['tag'] == 'head') { + $up = unpack('n*', substr($table, 8, 4)); + $adjustment[0] = $up[1]; + $adjustment[1] = $up[2]; + $checksum = $this->sub32($checksum, $adjustment); + } + $xchecksum = $t['checksum']; + if ($xchecksum != $checksum) { + throw new \Mpdf\Exception\FontException(sprintf('TTF file "%s": invalid checksum %s table: %s (expected %s)', $this->filename, dechex($checksum[0]) . dechex($checksum[1]), $t['tag'], dechex($xchecksum[0]) . dechex($xchecksum[1]))); + } + } + } + } + + function sub32($x, $y) + { + $xlo = $x[1]; + $xhi = $x[0]; + $ylo = $y[1]; + $yhi = $y[0]; + if ($ylo > $xlo) { + $xlo += 1 << 16; + $yhi += 1; + } + $reslo = $xlo - $ylo; + if ($yhi > $xhi) { + $xhi += 1 << 16; + } + $reshi = $xhi - $yhi; + $reshi = $reshi & 0xFFFF; + + return [$reshi, $reslo]; + } + + function calcChecksum($data) + { + if (strlen($data) % 4) { + $data .= str_repeat("\0", (4 - (strlen($data) % 4))); + } + $len = strlen($data); + $hi = 0x0000; + $lo = 0x0000; + for ($i = 0; $i < $len; $i += 4) { + $hi += (ord($data[$i]) << 8) + ord($data[$i + 1]); + $lo += (ord($data[$i + 2]) << 8) + ord($data[$i + 3]); + $hi += ($lo >> 16) & 0xFFFF; + $lo = $lo & 0xFFFF; + } + + return [$hi, $lo]; + } + + function get_table_pos($tag) + { + $offset = isset($this->tables[$tag]['offset']) ? $this->tables[$tag]['offset'] : null; + $length = isset($this->tables[$tag]['length']) ? $this->tables[$tag]['length'] : null; + + return [$offset, $length]; + } + + function seek($pos) + { + $this->_pos = $pos; + fseek($this->fh, $this->_pos); + } + + function skip($delta) + { + $this->_pos = $this->_pos + $delta; + fseek($this->fh, $delta, SEEK_CUR); + } + + function seek_table($tag, $offset_in_table = 0) + { + $tpos = $this->get_table_pos($tag); + $this->_pos = $tpos[0] + $offset_in_table; + fseek($this->fh, $this->_pos); + + return $this->_pos; + } + + function read_tag() + { + $this->_pos += 4; + + return fread($this->fh, 4); + } + + function read_short() + { + $this->_pos += 2; + $s = fread($this->fh, 2); + $a = (ord($s[0]) << 8) + ord($s[1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + + return $a; + } + + function unpack_short($s) + { + $a = (ord($s[0]) << 8) + ord($s[1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + + return $a; + } + + function read_ushort() + { + $this->_pos += 2; + $s = fread($this->fh, 2); + + return (ord($s[0]) << 8) + ord($s[1]); + } + + function read_ulong() + { + $this->_pos += 4; + $s = fread($this->fh, 4); + + // if large uInt32 as an integer, PHP converts it to -ve + return (ord($s[0]) * 16777216) + (ord($s[1]) << 16) + (ord($s[2]) << 8) + ord($s[3]); // 16777216 = 1<<24 + } + + function get_ushort($pos) + { + fseek($this->fh, $pos); + $s = fread($this->fh, 2); + + return (ord($s[0]) << 8) + ord($s[1]); + } + + function get_ulong($pos) + { + fseek($this->fh, $pos); + $s = fread($this->fh, 4); + + // iF large uInt32 as an integer, PHP converts it to -ve + return (ord($s[0]) * 16777216) + (ord($s[1]) << 16) + (ord($s[2]) << 8) + ord($s[3]); // 16777216 = 1<<24 + } + + function pack_short($val) + { + if ($val < 0) { + $val = abs($val); + $val = ~$val; + $val += 1; + } + + return pack("n", $val); + } + + function splice($stream, $offset, $value) + { + return substr($stream, 0, $offset) . $value . substr($stream, $offset + strlen($value)); + } + + function _set_ushort($stream, $offset, $value) + { + $up = pack("n", $value); + + return $this->splice($stream, $offset, $up); + } + + function _set_short($stream, $offset, $val) + { + if ($val < 0) { + $val = abs($val); + $val = ~$val; + $val += 1; + } + $up = pack("n", $val); + + return $this->splice($stream, $offset, $up); + } + + function get_chunk($pos, $length) + { + fseek($this->fh, $pos); + if ($length < 1) { + return ''; + } + + return (fread($this->fh, $length)); + } + + function get_table($tag) + { + list($pos, $length) = $this->get_table_pos($tag); + if ($length == 0) { + return ''; + } + fseek($this->fh, $pos); + + return (fread($this->fh, $length)); + } + + function add($tag, $data) + { + if ($tag == 'head') { + $data = $this->splice($data, 8, "\0\0\0\0"); + } + $this->otables[$tag] = $data; + } + + ///////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// + + function extractInfo($debug = false, $BMPonly = false, $kerninfo = false, $useOTL = 0) + { + $this->panose = []; + $this->sFamilyClass = 0; + $this->sFamilySubClass = 0; + /////////////////////////////////// + // name - Naming table + /////////////////////////////////// + $name_offset = $this->seek_table("name"); + $format = $this->read_ushort(); + if ($format != 0 && $format != 1) { + throw new \Mpdf\Exception\FontException("Error loading font: Unknown name table format " . $format); + } + $numRecords = $this->read_ushort(); + $string_data_offset = $name_offset + $this->read_ushort(); + $names = [1 => '', 2 => '', 3 => '', 4 => '', 6 => '']; + $K = array_keys($names); + $nameCount = count($names); + for ($i = 0; $i < $numRecords; $i++) { + $platformId = $this->read_ushort(); + $encodingId = $this->read_ushort(); + $languageId = $this->read_ushort(); + $nameId = $this->read_ushort(); + $length = $this->read_ushort(); + $offset = $this->read_ushort(); + if (!in_array($nameId, $K)) { + continue; + } + $N = ''; + if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name + $opos = $this->_pos; + $this->seek($string_data_offset + $offset); + if ($length % 2 != 0) { + throw new \Mpdf\Exception\FontException("Error loading font: PostScript name is UTF-16BE string of odd length"); + } + $length /= 2; + $N = ''; + while ($length > 0) { + $char = $this->read_ushort(); + $N .= (chr($char)); + $length -= 1; + } + $this->_pos = $opos; + $this->seek($opos); + } else { + if ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name + $opos = $this->_pos; + $N = $this->get_chunk($string_data_offset + $offset, $length); + $this->_pos = $opos; + $this->seek($opos); + } + } + if ($N && $names[$nameId] == '') { + $names[$nameId] = $N; + $nameCount -= 1; + if ($nameCount == 0) { + break; + } + } + } + if ($names[6]) { + $psName = $names[6]; + } else { + if ($names[4]) { + $psName = preg_replace('/ /', '-', $names[4]); + } else { + if ($names[1]) { + $psName = preg_replace('/ /', '-', $names[1]); + } else { + $psName = ''; + } + } + } + if (!$psName) { + throw new \Mpdf\Exception\FontException("Error loading font: Could not find PostScript font name: " . $this->filename); + } + if ($debug) { + for ($i = 0; $i < count($psName); $i++) { + $c = $psName[$i]; + $oc = ord($c); + if ($oc > 126 || strpos(' [](){}<>/%', $c) !== false) { + throw new \Mpdf\Exception\FontException("psName=" . $psName . " contains invalid character " . $c . " ie U+" . ord($c)); + } + } + } + $this->name = $psName; + if ($names[1]) { + $this->familyName = $names[1]; + } else { + $this->familyName = $psName; + } + if ($names[2]) { + $this->styleName = $names[2]; + } else { + $this->styleName = 'Regular'; + } + if ($names[4]) { + $this->fullName = $names[4]; + } else { + $this->fullName = $psName; + } + if ($names[3]) { + $this->uniqueFontID = $names[3]; + } else { + $this->uniqueFontID = $psName; + } + + if ($names[6]) { + $this->fullName = $names[6]; + } + + /////////////////////////////////// + // head - Font header table + /////////////////////////////////// + $this->seek_table("head"); + if ($debug) { + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown head table version ' . $ver_maj . '.' . $ver_min); + } + $this->fontRevision = $this->read_ushort() . $this->read_ushort(); + + $this->skip(4); + $magic = $this->read_ulong(); + if ($magic != 0x5F0F3CF5) { + throw new \Mpdf\Exception\FontException('Error loading font: Invalid head table magic ' . $magic); + } + $this->skip(2); + } else { + $this->skip(18); + } + $this->unitsPerEm = $unitsPerEm = $this->read_ushort(); + $scale = 1000 / $unitsPerEm; + $this->skip(16); + $xMin = $this->read_short(); + $yMin = $this->read_short(); + $xMax = $this->read_short(); + $yMax = $this->read_short(); + $this->bbox = [($xMin * $scale), ($yMin * $scale), ($xMax * $scale), ($yMax * $scale)]; + $this->skip(3 * 2); + $indexToLocFormat = $this->read_ushort(); + $glyphDataFormat = $this->read_ushort(); + if ($glyphDataFormat != 0) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown glyph data format ' . $glyphDataFormat); + } + + /////////////////////////////////// + // hhea metrics table + /////////////////////////////////// + // ttf2t1 seems to use this value rather than the one in OS/2 - so put in for compatibility + if (isset($this->tables["hhea"])) { + $this->seek_table("hhea"); + $this->skip(4); + $hheaAscender = $this->read_short(); + $hheaDescender = $this->read_short(); + $this->ascent = ($hheaAscender * $scale); + $this->descent = ($hheaDescender * $scale); + } + + /////////////////////////////////// + // OS/2 - OS/2 and Windows metrics table + /////////////////////////////////// + if (isset($this->tables["OS/2"])) { + $this->seek_table("OS/2"); + $version = $this->read_ushort(); + $this->skip(2); + $usWeightClass = $this->read_ushort(); + $this->skip(2); + $fsType = $this->read_ushort(); + if ($fsType == 0x0002 || ($fsType & 0x0300) != 0) { + global $overrideTTFFontRestriction; + if (!$overrideTTFFontRestriction) { + throw new \Mpdf\Exception\FontException('Font file ' . $this->filename . ' cannot be embedded due to copyright restrictions.'); + } + $this->restrictedUse = true; + } + $this->skip(20); + $sF = $this->read_short(); + $this->sFamilyClass = ($sF >> 8); + $this->sFamilySubClass = ($sF & 0xFF); + $this->_pos += 10; //PANOSE = 10 byte length + $panose = fread($this->fh, 10); + $this->panose = []; + for ($p = 0; $p < strlen($panose); $p++) { + $this->panose[] = ord($panose[$p]); + } + $this->skip(26); + $sTypoAscender = $this->read_short(); + $sTypoDescender = $this->read_short(); + if (!$this->ascent) { + $this->ascent = ($sTypoAscender * $scale); + } + if (!$this->descent) { + $this->descent = ($sTypoDescender * $scale); + } + if ($version > 1) { + $this->skip(16); + $sCapHeight = $this->read_short(); + $this->capHeight = ($sCapHeight * $scale); + } else { + $this->capHeight = $this->ascent; + } + } else { + $usWeightClass = 500; + if (!$this->ascent) { + $this->ascent = ($yMax * $scale); + } + if (!$this->descent) { + $this->descent = ($yMin * $scale); + } + $this->capHeight = $this->ascent; + } + $this->stemV = 50 + intval(pow(($usWeightClass / 65.0), 2)); + + /////////////////////////////////// + // post - PostScript table + /////////////////////////////////// + $this->seek_table("post"); + if ($debug) { + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj < 1 || $ver_maj > 4) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown post table version ' . $ver_maj); + } + } else { + $this->skip(4); + } + $this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0; + $this->underlinePosition = $this->read_short() * $scale; + $this->underlineThickness = $this->read_short() * $scale; + $isFixedPitch = $this->read_ulong(); + + $this->flags = 4; + + if ($this->italicAngle != 0) { + $this->flags = $this->flags | 64; + } + if ($usWeightClass >= 600) { + $this->flags = $this->flags | 262144; + } + if ($isFixedPitch) { + $this->flags = $this->flags | 1; + } + + /////////////////////////////////// + // hhea - Horizontal header table + /////////////////////////////////// + $this->seek_table("hhea"); + if ($debug) { + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown hhea table version %s', $ver_maj)); + } + $this->skip(28); + } else { + $this->skip(32); + } + $metricDataFormat = $this->read_ushort(); + if ($metricDataFormat != 0) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown horizontal metric data format ' . $metricDataFormat); + } + $numberOfHMetrics = $this->read_ushort(); + if ($numberOfHMetrics == 0) { + throw new \Mpdf\Exception\FontException('Error loading font: Number of horizontal metrics is 0'); + } + + /////////////////////////////////// + // maxp - Maximum profile table + /////////////////////////////////// + $this->seek_table("maxp"); + if ($debug) { + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown maxp table version ' . $ver_maj); + } + } else { + $this->skip(4); + } + $numGlyphs = $this->read_ushort(); + + /////////////////////////////////// + // cmap - Character to glyph index mapping table + /////////////////////////////////// + $cmap_offset = $this->seek_table("cmap"); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + if (!$unicode_cmap_offset) { + $unicode_cmap_offset = $cmap_offset + $offset; + } + if ($BMPonly) { + break; + } + } + } // Microsoft, Unicode Format 12 table HKCS + else { + if ((($platformID == 3 && $encodingID == 10) || $platformID == 0) && !$BMPonly) { + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 12) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + } + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\Exception\FontException('Font (' . $this->filename . ') does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)'); + } + + $sipset = false; + $smpset = false; + + // mPDF 5.7.1 + $this->GSUBScriptLang = []; + $this->rtlPUAstr = ''; + $this->rtlPUAarr = []; + $this->GSUBFeatures = []; + $this->GSUBLookups = []; + $this->GPOSScriptLang = []; + $this->GPOSFeatures = []; + $this->GPOSLookups = []; + $this->glyphIDtoUni = ''; + + // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above + if ($format == 12 && !$BMPonly) { + $this->maxUniChar = 0; + $this->seek($unicode_cmap_offset + 4); + $length = $this->read_ulong(); + $limit = $unicode_cmap_offset + $length; + $this->skip(4); + + $nGroups = $this->read_ulong(); + + $glyphToChar = []; + $charToGlyph = []; + for ($i = 0; $i < $nGroups; $i++) { + $startCharCode = $this->read_ulong(); + $endCharCode = $this->read_ulong(); + $startGlyphCode = $this->read_ulong(); + if ($endCharCode > 0x20000 && $endCharCode < 0x2FFFF) { + $sipset = true; + } else { + if ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) { + $smpset = true; + } + } + $offset = 0; + for ($unichar = $startCharCode; $unichar <= $endCharCode; $unichar++) { + $glyph = $startGlyphCode + $offset; + $offset++; + if ($unichar < 0x30000) { + $charToGlyph[$unichar] = $glyph; + $this->maxUniChar = max($unichar, $this->maxUniChar); + $glyphToChar[$glyph][] = $unichar; + } + } + } + } else { + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + } + $this->sipset = $sipset; + $this->smpset = $smpset; + + /////////////////////////////////// + // mPDF 5.7.1 + // Map Unmapped glyphs - from $numGlyphs + if ($this->useOTL) { + $bctr = 0xE000; + for ($gid = 1; $gid < $numGlyphs; $gid++) { + if (!isset($glyphToChar[$gid])) { + while (isset($charToGlyph[$bctr])) { + $bctr++; + } // Avoid overwriting a glyph already mapped in PUA + if (($bctr > 0xF8FF) && ($bctr < 0x2CEB0)) { + if (!$BMPonly) { + $bctr = 0x2CEB0; // Use unassigned area 0x2CEB0 to 0x2F7FF (space for 10,000 characters) + $this->sipset = $sipset = true; // forces subsetting; also ensure charwidths are saved + while (isset($charToGlyph[$bctr])) { + $bctr++; + } + } else { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)', $this->filename)); + } + } + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $this->maxUniChar = max($bctr, $this->maxUniChar); + $bctr++; + } + } + } + $this->glyphToChar = $glyphToChar; + $this->charToGlyph = $charToGlyph; + /////////////////////////////////// + // mPDF 5.7.1 OpenType Layout tables + $this->GSUBScriptLang = []; + $this->rtlPUAstr = ''; + $this->rtlPUAarr = []; + if ($useOTL) { + $this->_getGDEFtables(); + list($this->GSUBScriptLang, $this->GSUBFeatures, $this->GSUBLookups, $this->rtlPUAstr, $this->rtlPUAarr) = $this->_getGSUBtables(); + list($this->GPOSScriptLang, $this->GPOSFeatures, $this->GPOSLookups) = $this->_getGPOStables(); + $this->glyphIDtoUni = str_pad('', 256 * 256 * 3, "\x00"); + foreach ($glyphToChar as $gid => $arr) { + if (isset($glyphToChar[$gid][0])) { + $char = $glyphToChar[$gid][0]; + if ($char != 0 && $char != 65535) { + $this->glyphIDtoUni[$gid * 3] = chr($char >> 16); + $this->glyphIDtoUni[$gid * 3 + 1] = chr(($char >> 8) & 0xFF); + $this->glyphIDtoUni[$gid * 3 + 2] = chr($char & 0xFF); + } + } + } + } + /////////////////////////////////// + /////////////////////////////////// + // hmtx - Horizontal metrics table + /////////////////////////////////// + $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale); + + /////////////////////////////////// + // kern - Kerning pair table + /////////////////////////////////// + if ($kerninfo) { + // Recognises old form of Kerning table - as required by Windows - Format 0 only + $kern_offset = $this->seek_table("kern"); + $version = $this->read_ushort(); + $nTables = $this->read_ushort(); + // subtable header + $sversion = $this->read_ushort(); + $slength = $this->read_ushort(); + $scoverage = $this->read_ushort(); + $format = $scoverage >> 8; + if ($kern_offset && $version == 0 && $format == 0) { + // Format 0 + $nPairs = $this->read_ushort(); + $this->skip(6); + for ($i = 0; $i < $nPairs; $i++) { + $left = $this->read_ushort(); + $right = $this->read_ushort(); + $val = $this->read_short(); + if (count($glyphToChar[$left]) == 1 && count($glyphToChar[$right]) == 1) { + if ($left != 32 && $right != 32) { + $this->kerninfo[$glyphToChar[$left][0]][$glyphToChar[$right][0]] = intval($val * $scale); + } + } + } + } + } + } + + ///////////////////////////////////////////////////////////////////////////////////////// + function _getGDEFtables() + { + /////////////////////////////////// + // GDEF - Glyph Definition + /////////////////////////////////// + // http://www.microsoft.com/typography/otspec/gdef.htm + if (isset($this->tables["GDEF"])) { + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h1>GDEF table</h1>'); + } + $gdef_offset = $this->seek_table("GDEF"); + // ULONG Version of the GDEF table-currently 0x00010000 + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + // Version 0x00010002 of GDEF header contains additional Offset to a list defining mark glyph set definitions (MarkGlyphSetDef) + $GlyphClassDef_offset = $this->read_ushort(); + $AttachList_offset = $this->read_ushort(); + $LigCaretList_offset = $this->read_ushort(); + $MarkAttachClassDef_offset = $this->read_ushort(); + if ($ver_min == 2) { + $MarkGlyphSetsDef_offset = $this->read_ushort(); + } + + // GlyphClassDef + $this->seek($gdef_offset + $GlyphClassDef_offset); + /* + 1 Base glyph (single character, spacing glyph) + 2 Ligature glyph (multiple character, spacing glyph) + 3 Mark glyph (non-spacing combining glyph) + 4 Component glyph (part of single character, spacing glyph) + */ + $GlyphByClass = $this->_getClassDefinitionTable(); + + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h2>Glyph classes</h2>'); + } + + if (isset($GlyphByClass[1]) && count($GlyphByClass[1]) > 0) { + $this->GlyphClassBases = $this->formatClassArr($GlyphByClass[1]); + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Glyph class 1</h3>'); + $this->mpdf->WriteHTML('<h5>Base glyph (single character, spacing glyph)</h5>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($GlyphByClass[1] as $g) { + $html .= '&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } else { + $this->GlyphClassBases = ''; + } + if (isset($GlyphByClass[2]) && count($GlyphByClass[2]) > 0) { + $this->GlyphClassLigatures = $this->formatClassArr($GlyphByClass[2]); + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Glyph class 2</h3>'); + $this->mpdf->WriteHTML('<h5>Ligature glyph (multiple character, spacing glyph)</h5>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($GlyphByClass[2] as $g) { + $html .= '&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } else { + $this->GlyphClassLigatures = ''; + } + if (isset($GlyphByClass[3]) && count($GlyphByClass[3]) > 0) { + $this->GlyphClassMarks = $this->formatClassArr($GlyphByClass[3]); + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Glyph class 3</h3>'); + $this->mpdf->WriteHTML('<h5>Mark glyph (non-spacing combining glyph)</h5>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($GlyphByClass[3] as $g) { + $html .= '◌&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } else { + $this->GlyphClassMarks = ''; + } + if (isset($GlyphByClass[4]) && count($GlyphByClass[4]) > 0) { + $this->GlyphClassComponents = $this->formatClassArr($GlyphByClass[4]); + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Glyph class 4</h3>'); + $this->mpdf->WriteHTML('<h5>Component glyph (part of single character, spacing glyph)</h5>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($GlyphByClass[4] as $g) { + $html .= '&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } else { + $this->GlyphClassComponents = ''; + } + + $Marks = $GlyphByClass[3]; // to use for MarkAttachmentType + + /* Required for GPOS + // Attachment List + if ($AttachList_offset) { + $this->seek($gdef_offset+$AttachList_offset ); + } + The Attachment Point List table (AttachmentList) identifies all the attachment points defined in the GPOS table and their associated glyphs so a client can quickly access coordinates for each glyph's attachment points. As a result, the client can cache coordinates for attachment points along with glyph bitmaps and avoid recalculating the attachment points each time it displays a glyph. Without this table, processing speed would be slower because the client would have to decode the GPOS lookups that define attachment points and compile the points in a list. + + The Attachment List table (AttachList) may be used to cache attachment point coordinates along with glyph bitmaps. + + The table consists of an offset to a Coverage table (Coverage) listing all glyphs that define attachment points in the GPOS table, a count of the glyphs with attachment points (GlyphCount), and an array of offsets to AttachPoint tables (AttachPoint). The array lists the AttachPoint tables, one for each glyph in the Coverage table, in the same order as the Coverage Index. + AttachList table + Type Name Description + Offset Coverage Offset to Coverage table - from beginning of AttachList table + uint16 GlyphCount Number of glyphs with attachment points + Offset AttachPoint[GlyphCount] Array of offsets to AttachPoint tables-from beginning of AttachList table-in Coverage Index order + + An AttachPoint table consists of a count of the attachment points on a single glyph (PointCount) and an array of contour indices of those points (PointIndex), listed in increasing numerical order. + + AttachPoint table + Type Name Description + uint16 PointCount Number of attachment points on this glyph + uint16 PointIndex[PointCount] Array of contour point indices -in increasing numerical order + + See Example 3 - http://www.microsoft.com/typography/otspec/gdef.htm + */ + + // Ligature Caret List + // The Ligature Caret List table (LigCaretList) defines caret positions for all the ligatures in a font. + // Not required for mDPF + // MarkAttachmentType + if ($MarkAttachClassDef_offset) { + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h1>Mark Attachment Types</h1>'); + } + $this->seek($gdef_offset + $MarkAttachClassDef_offset); + $MarkAttachmentTypes = $this->_getClassDefinitionTable(); + foreach ($MarkAttachmentTypes as $class => $glyphs) { + if (is_array($Marks) && count($Marks)) { + $mat = array_diff($Marks, $MarkAttachmentTypes[$class]); + sort($mat, SORT_STRING); + } else { + $mat = []; + } + + $this->MarkAttachmentType[$class] = $this->formatClassArr($mat); + + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Mark Attachment Type: ' . $class . '</h3>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($glyphs as $g) { + $html .= '◌&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } + } else { + $this->MarkAttachmentType = []; + } + + // MarkGlyphSets only in Version 0x00010002 of GDEF + if ($ver_min == 2 && $MarkGlyphSetsDef_offset) { + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h1>Mark Glyph Sets</h1>'); + } + $this->seek($gdef_offset + $MarkGlyphSetsDef_offset); + $MarkSetTableFormat = $this->read_ushort(); + $MarkSetCount = $this->read_ushort(); + $MarkSetOffset = []; + for ($i = 0; $i < $MarkSetCount; $i++) { + $MarkSetOffset[] = $this->read_ulong(); + } + for ($i = 0; $i < $MarkSetCount; $i++) { + $this->seek($MarkSetOffset[$i]); + $glyphs = $this->_getCoverage(); + $this->MarkGlyphSets[$i] = $this->formatClassArr($glyphs); + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>Mark Glyph Set class: ' . $i . '</h3>'); + $html = ''; + $html .= '<div class="glyphs">'; + foreach ($glyphs as $g) { + $html .= '◌&#x' . $g . '; '; + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + } + } + } else { + $this->MarkGlyphSets = []; + } + } else { + $this->mpdf->WriteHTML('<div>GDEF table not defined</div>'); + } + +//echo $this->GlyphClassMarks ; exit; +//print_r($GlyphClass); exit; +//print_r($GlyphByClass); exit; + } + + function _getClassDefinitionTable($offset = 0) + { + + if ($offset > 0) { + $this->seek($offset); + } + + // NB Any glyph not included in the range of covered GlyphIDs automatically belongs to Class 0. This is not returned by this function + $ClassFormat = $this->read_ushort(); + $GlyphByClass = []; + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $gid = $StartGlyph + $i; + $class = $this->read_ushort(); + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]); + } + } else { + if ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $startGlyphID = $this->read_ushort(); + $endGlyphID = $this->read_ushort(); + $class = $this->read_ushort(); + for ($gid = $startGlyphID; $gid <= $endGlyphID; $gid++) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]); + } + } + } + } + ksort($GlyphByClass); + + return $GlyphByClass; + } + + function _getGSUBtables() + { + /////////////////////////////////// + // GSUB - Glyph Substitution + /////////////////////////////////// + if (isset($this->tables["GSUB"])) { + $this->mpdf->WriteHTML('<h1>GSUB Tables</h1>'); + $ffeats = []; + $gsub_offset = $this->seek_table("GSUB"); + $this->skip(4); + $ScriptList_offset = $gsub_offset + $this->read_ushort(); + $FeatureList_offset = $gsub_offset + $this->read_ushort(); + $LookupList_offset = $gsub_offset + $this->read_ushort(); + + // ScriptList + $this->seek($ScriptList_offset); + $ScriptCount = $this->read_ushort(); + for ($i = 0; $i < $ScriptCount; $i++) { + $ScriptTag = $this->read_tag(); // = "beng", "deva" etc. + $ScriptTableOffset = $this->read_ushort(); + $ffeats[$ScriptTag] = $ScriptList_offset + $ScriptTableOffset; + } + + // Script Table + foreach ($ffeats as $t => $o) { + $ls = []; + $this->seek($o); + $DefLangSys_offset = $this->read_ushort(); + if ($DefLangSys_offset > 0) { + $ls['DFLT'] = $DefLangSys_offset + $o; + } + $LangSysCount = $this->read_ushort(); + for ($i = 0; $i < $LangSysCount; $i++) { + $LangTag = $this->read_tag(); // = + $LangTableOffset = $this->read_ushort(); + $ls[$LangTag] = $o + $LangTableOffset; + } + $ffeats[$t] = $ls; + } +//print_r($ffeats); exit; + // Get FeatureIndexList + // LangSys Table - from first listed langsys + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = []; + $langsystable_offset = $o; + $this->seek($langsystable_offset); + $LookUpOrder = $this->read_ushort(); //==NULL + $ReqFeatureIndex = $this->read_ushort(); + if ($ReqFeatureIndex != 0xFFFF) { + $FeatureIndex[] = $ReqFeatureIndex; + } + $FeatureCount = $this->read_ushort(); + for ($i = 0; $i < $FeatureCount; $i++) { + $FeatureIndex[] = $this->read_ushort(); // = index of feature + } + $ffeats[$st][$t] = $FeatureIndex; + } + } +//print_r($ffeats); exit; + // Feauture List => LookupListIndex es + $this->seek($FeatureList_offset); + $FeatureCount = $this->read_ushort(); + $Feature = []; + for ($i = 0; $i < $FeatureCount; $i++) { + $Feature[$i] = ['tag' => $this->read_tag()]; + $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort(); + } + for ($i = 0; $i < $FeatureCount; $i++) { + $this->seek($Feature[$i]['offset']); + $this->read_ushort(); // null + $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort(); + $Feature[$i]['LookupListIndex'] = []; + for ($c = 0; $c < $Lookupcount; $c++) { + $Feature[$i]['LookupListIndex'][] = $this->read_ushort(); + } + } + + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = $ffeats[$st][$t]; + foreach ($FeatureIndex as $k => $fi) { + $ffeats[$st][$t][$k] = $Feature[$fi]; + } + } + } + //===================================================================================== + $gsub = []; + $GSUBScriptLang = []; + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $langsys) { + $lg = []; + foreach ($langsys as $ft) { + $lg[$ft['LookupListIndex'][0]] = $ft; + } + // list of Lookups in order they need to be run i.e. order listed in Lookup table + ksort($lg); + foreach ($lg as $ft) { + $gsub[$st][$t][$ft['tag']] = $ft['LookupListIndex']; + } + if (!isset($GSUBScriptLang[$st])) { + $GSUBScriptLang[$st] = ''; + } + $GSUBScriptLang[$st] .= $t . ' '; + } + } + +//print_r($gsub); exit; + + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>GSUB Scripts & Languages</h3>'); + $this->mpdf->WriteHTML('<div class="glyphs">'); + $html = ''; + if (count($gsub)) { + foreach ($gsub as $st => $g) { + $html .= '<h5>' . $st . '</h5>'; + foreach ($g as $l => $t) { + $html .= '<div><a href="font_dump_OTL.php?script=' . $st . '&lang=' . $l . '">' . $l . '</a></b>: '; + foreach ($t as $tag => $o) { + $html .= $tag . ' '; + } + $html .= '</div>'; + } + } + } else { + $html .= '<div>No entries in GSUB table.</div>'; + } + $this->mpdf->WriteHTML($html); + $this->mpdf->WriteHTML('</div>'); + + return 0; + } + + //===================================================================================== + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $GSLookup = []; + $Offsets = []; + $SubtableCount = []; + for ($i = 0; $i < $LookupCount; $i++) { + $Offsets[$i] = $LookupList_offset + $this->read_ushort(); + } + for ($i = 0; $i < $LookupCount; $i++) { + $this->seek($Offsets[$i]); + $GSLookup[$i]['Type'] = $this->read_ushort(); + $GSLookup[$i]['Flag'] = $flag = $this->read_ushort(); + $GSLookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort(); + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $GSLookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort(); + } + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) == 0x0010) { + $GSLookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } + // else { $GSLookup[$i]['MarkFilteringSet'] = ''; } + // Lookup Type 7: Extension + if ($GSLookup[$i]['Type'] == 7) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $this->seek($GSLookup[$i]['Subtables'][$c]); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $GSLookup[$i]['Subtables'][$c] = $GSLookup[$i]['Subtables'][$c] + $this->read_ulong(); + } + $GSLookup[$i]['Type'] = $type; + } + } + +//print_r($GSLookup); exit; + //===================================================================================== + // Process Whole LookupList - Get LuCoverage = Lookup coverage just for first glyph + $this->GSLuCoverage = []; + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $GSLookup[$i]['SubtableCount']; $c++) { + $this->seek($GSLookup[$i]['Subtables'][$c]); + $PosFormat = $this->read_ushort(); + + if ($GSLookup[$i]['Type'] == 5 && $PosFormat == 3) { + $this->skip(4); + } else { + if ($GSLookup[$i]['Type'] == 6 && $PosFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + $this->skip(2 * $BacktrackGlyphCount + 2); + } + } + // NB Coverage only looks at glyphs for position 1 (i.e. 5.3 and 6.3) // NEEDS TO READ ALL ******************** + $Coverage = $GSLookup[$i]['Subtables'][$c] + $this->read_ushort(); + $this->seek($Coverage); + $glyphs = $this->_getCoverage(); + $this->GSLuCoverage[$i][$c] = implode('|', $glyphs); + } + } + +// $this->GSLuCoverage and $GSLookup + //===================================================================================== + $s = '<?php +$GSLuCoverage = ' . var_export($this->GSLuCoverage, true) . '; +?>'; + + //===================================================================================== + $s = '<?php +$GlyphClassBases = \'' . $this->GlyphClassBases . '\'; +$GlyphClassMarks = \'' . $this->GlyphClassMarks . '\'; +$GlyphClassLigatures = \'' . $this->GlyphClassLigatures . '\'; +$GlyphClassComponents = \'' . $this->GlyphClassComponents . '\'; +$MarkGlyphSets = ' . var_export($this->MarkGlyphSets, true) . '; +$MarkAttachmentType = ' . var_export($this->MarkAttachmentType, true) . '; +?>'; + + //===================================================================================== + //===================================================================================== + //===================================================================================== +// Now repeats as original to get Substitution rules + //===================================================================================== + //===================================================================================== + //===================================================================================== + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $Lookup = []; + for ($i = 0; $i < $LookupCount; $i++) { + $Lookup[$i]['offset'] = $LookupList_offset + $this->read_ushort(); + } + for ($i = 0; $i < $LookupCount; $i++) { + $this->seek($Lookup[$i]['offset']); + $Lookup[$i]['Type'] = $this->read_ushort(); + $Lookup[$i]['Flag'] = $flag = $this->read_ushort(); + $Lookup[$i]['SubtableCount'] = $this->read_ushort(); + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['offset'] + $this->read_ushort(); + } + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) == 0x0010) { + $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } else { + $Lookup[$i]['MarkFilteringSet'] = ''; + } + + // Lookup Type 7: Extension + if ($Lookup[$i]['Type'] == 7) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $this->seek($Lookup[$i]['Subtable'][$c]['Offset']); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ulong(); + } + $Lookup[$i]['Type'] = $type; + } + } + +//print_r($Lookup); exit; + //===================================================================================== + // Process (1) Whole LookupList + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $this->seek($Lookup[$i]['Subtable'][$c]['Offset']); + $SubstFormat = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['Format'] = $SubstFormat; + + /* + Lookup['Type'] Enumeration table for glyph substitution + Value Type Description + 1 Single Replace one glyph with one glyph + 2 Multiple Replace one glyph with more than one glyph + 3 Alternate Replace one glyph with one of many glyphs + 4 Ligature Replace multiple glyphs with one glyph + 5 Context Replace one or more glyphs in context + 6 Chaining Context Replace one or more glyphs in chained context + 7 Extension Substitution Extension mechanism for other substitutions (i.e. this excludes the Extension type substitution itself) + 8 Reverse chaining context single Applied in reverse order, replace single glyph in chaining context + */ + + // LookupType 1: Single Substitution Subtable + if ($Lookup[$i]['Type'] == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + if ($SubstFormat == 1) { // Calculated output glyph indices + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'] = $this->read_short(); + } else { + if ($SubstFormat == 2) { // Specified output glyph indices + $GlyphCount = $this->read_ushort(); + for ($g = 0; $g < $GlyphCount; $g++) { + $Lookup[$i]['Subtable'][$c]['Glyphs'][] = $this->read_ushort(); + } + } + } + } // LookupType 2: Multiple Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SequenceCount'] = $SequenceCount = $this->read_short(); + for ($s = 0; $s < $SequenceCount; $s++) { + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $SequenceCount; $s++) { + // Sequence Tables + $this->seek($Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['GlyphCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['GlyphCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['SubstituteGlyphID'][] = $this->read_ushort(); + } + } + } // LookupType 3: Alternate Forms + else { + if ($Lookup[$i]['Type'] == 3) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['AlternateSetCount'] = $AlternateSetCount = $this->read_short(); + for ($s = 0; $s < $AlternateSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + + for ($s = 0; $s < $AlternateSetCount; $s++) { + // AlternateSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['GlyphCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['GlyphCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['SubstituteGlyphID'][] = $this->read_ushort(); + } + } + } // LookupType 4: Ligature Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 4) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LigSetCount'] = $LigSetCount = $this->read_short(); + for ($s = 0; $s < $LigSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $LigSetCount; $s++) { + // LigatureSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g] = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] + $this->read_ushort(); + } + } + for ($s = 0; $s < $LigSetCount; $s++) { + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + // Ligature tables + $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g]); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount'] = $this->read_ushort(); + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['GlyphID'][$l] = $this->read_ushort(); + } + } + } + } // LookupType 5: Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 5) { + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSetCount'] = $SubRuleSetCount = $this->read_short(); + for ($s = 0; $s < $SubRuleSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $SubRuleSetCount; $s++) { + // SubRuleSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g] = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] + $this->read_ushort(); + } + } + for ($s = 0; $s < $SubRuleSetCount; $s++) { + // SubRule Tables + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $g++) { + // Ligature tables + $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g]); + + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['GlyphCount'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstCount'] = $this->read_ushort(); + // "Input"::[GlyphCount - 1]::Array of input GlyphIDs-start with second glyph + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['GlyphCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['Input'][$l] = $this->read_ushort(); + } + // "SubstLookupRecord"::[SubstCount]::Array of SubstLookupRecords-in design order + for ($l = 0; $l < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['SequenceIndex'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['LookupListIndex'] = $this->read_ushort(); + } + } + } + } // Format 2: Class-based Context Glyph Substitution + else { + if ($SubstFormat == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubClassSetCnt'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][] = 0; + } else { + $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $offset; + } + } + } else { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Lookup[$i]['Type'] . ", Format " . $SubstFormat . " not supported (ttfontsuni.php)."); + } + } + } // LookupType 6: Chaining Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 6) { + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + else { + if ($SubstFormat == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['InputClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][] = $offset; + } else { + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $offset; + } + } + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + else { + if ($SubstFormat == 3) { + $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['InputGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageInput'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageLookahead'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['SubstCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex'] = $this->read_ushort(); + /* + Substitution Lookup Record + All contextual substitution subtables specify the substitution data in a Substitution Lookup Record (SubstLookupRecord). Each record contains a SequenceIndex, which indicates the position where the substitution will occur in the glyph sequence. In addition, a LookupListIndex identifies the lookup to be applied at the glyph position specified by the SequenceIndex. + */ + } + } + } + } + } else { + throw new \Mpdf\Exception\FontException("Lookup Type " . $Lookup[$i]['Type'] . " not supported."); + } + } + } + } + } + } + } + } +//print_r($Lookup); exit; + //===================================================================================== + // Process (2) Whole LookupList + // Get Coverage tables and prepare preg_replace + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $SubstFormat = $Lookup[$i]['Subtable'][$c]['Format']; + + // LookupType 1: Single Substitution Subtable 1 => 1 + if ($Lookup[$i]['Type'] == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(false); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = unicode_hex($this->glyphToChar[$glyphs[$g]][0]); + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + if (isset($Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])) { // Format 1 + $substitute[] = unicode_hex($this->glyphToChar[($glyphs[$g] + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])][0]); + } else { // Format 2 + $substitute[] = unicode_hex($this->glyphToChar[($Lookup[$i]['Subtable'][$c]['Glyphs'][$g])][0]); + } + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + } // LookupType 2: Multiple Substitution Subtable 1 => n + else { + if ($Lookup[$i]['Type'] == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$g]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + if (!isset($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID']) || count($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID']) == 0) { + continue; + } // Illegal for GlyphCount to be 0; either error in font, or something has gone wrong - lets carry on for now! + foreach ($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID'] as $sub) { + $substitute[] = unicode_hex($this->glyphToChar[$sub][0]); + } + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + } // LookupType 3: Alternate Forms 1 => 1 (only first alternate form is used) + else { + if ($Lookup[$i]['Type'] == 3) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$g]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + + for ($gl = 0; $gl < $Lookup[$i]['Subtable'][$c]['AlternateSets'][$g]['GlyphCount']; $gl++) { + $gid = $Lookup[$i]['Subtable'][$c]['AlternateSets'][$g]['SubstituteGlyphID'][$gl]; + $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); + } + + //$gid = $Lookup[$i]['Subtable'][$c]['AlternateSets'][$g]['SubstituteGlyphID'][0]; + //$substitute[] = unicode_hex($this->glyphToChar[$gid][0]); + + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + if ($i == 166) { + print_r($Lookup[$i]['Subtable']); + exit; + } + } // LookupType 4: Ligature Substitution Subtable n => 1 + else { + if ($Lookup[$i]['Type'] == 4) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + $LigSetCount = $Lookup[$i]['Subtable'][$c]['LigSetCount']; + for ($s = 0; $s < $LigSetCount; $s++) { + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$s]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']; $l++) { + $gid = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['GlyphID'][$l]; + $rpl = unicode_hex($this->glyphToChar[$gid][0]); + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $rpl, $Lookup[$i]['MarkFilteringSet'])) { + continue 2; + } + $replace[] = $rpl; + } + $gid = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph']; + $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute, 'CompCount' => $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']]; + } + } + } // LookupType 5: Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 5) { + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubRuleSetCount']; $s++) { + $SubRuleSet = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]; + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['FirstGlyph'] = $CoverageGlyphs[$s]; + for ($r = 0; $r < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $r++) { + $GlyphCount = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['GlyphCount']; + for ($g = 1; $g < $GlyphCount; $g++) { + $glyphID = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['Input'][$g]; + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + } + } + } // Format 2: Class-based Context Glyph Substitution + else { + if ($SubstFormat == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['ClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['InputClasses'] = $InputClasses; + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $s++) { + if ($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s]); + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRuleCnt'] = $SubClassRuleCnt = $this->read_ushort(); + $SubClassRule = []; + for ($b = 0; $b < $SubClassRuleCnt; $b++) { + $SubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b] = $SubClassRule[$b]; + } + } + } + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $s++) { + $SubClassRuleCnt = $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRuleCnt']; + for ($b = 0; $b < $SubClassRuleCnt; $b++) { + if ($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b]); + $Rule = []; + $Rule['InputGlyphCount'] = $this->read_ushort(); + $Rule['SubstCount'] = $this->read_ushort(); + for ($r = 1; $r < $Rule['InputGlyphCount']; $r++) { + $Rule['Input'][$r] = $this->read_ushort(); + } + for ($r = 0; $r < $Rule['SubstCount']; $r++) { + $Rule['SequenceIndex'][$r] = $this->read_ushort(); + $Rule['LookupListIndex'][$r] = $this->read_ushort(); + } + + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b] = $Rule; + } + } + } + } // Format 3: Coverage-based Context Glyph Substitution + else { + if ($SubstFormat == 3) { + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs'][] = implode("|", $glyphs); + } + throw new \Mpdf\Exception\FontException("Lookup Type 5, SubstFormat 3 not tested. Please report this with the name of font used - " . $this->fontkey); + } + } + } + } // LookupType 6: Chaining Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 6) { + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $ChainSubRuleSetCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; + + for ($s = 0; $s < $ChainSubRuleSetCnt; $s++) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s]); + $ChainSubRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleCount'] = $this->read_ushort(); + for ($r = 0; $r < $ChainSubRuleCnt; $r++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r] = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s] + $this->read_ushort(); + } + } + for ($s = 0; $s < $ChainSubRuleSetCnt; $s++) { + $ChainSubRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleCount']; + for ($r = 0; $r < $ChainSubRuleCnt; $r++) { + // ChainSubRule + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r]); + + $BacktrackGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphCount'] = $this->read_ushort(); + for ($g = 0; $g < $BacktrackGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $InputGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphCount'] = $this->read_ushort(); + for ($g = 1; $g < $InputGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $LookaheadGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphCount'] = $this->read_ushort(); + for ($g = 0; $g < $LookaheadGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $SubstCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SubstCount'] = $this->read_ushort(); + for ($lu = 0; $lu < $SubstCount; $lu++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SequenceIndex'][$lu] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookupListIndex'][$lu] = $this->read_ushort(); + } + } + } + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + else { + if ($SubstFormat == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $BacktrackClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['BacktrackClasses'] = $BacktrackClasses; + + $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['InputClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['InputClasses'] = $InputClasses; + + $LookaheadClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['LookaheadClasses'] = $LookaheadClasses; + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $s++) { + if ($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s]); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt'] = $ChainSubClassRuleCnt = $this->read_ushort(); + $ChainSubClassRule = []; + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { + $ChainSubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b] = $ChainSubClassRule[$b]; + } + } + } + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $s++) { + $ChainSubClassRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt']; + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { + if ($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b]); + $Rule = []; + $Rule['BacktrackGlyphCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['BacktrackGlyphCount']; $r++) { + $Rule['Backtrack'][$r] = $this->read_ushort(); + } + $Rule['InputGlyphCount'] = $this->read_ushort(); + for ($r = 1; $r < $Rule['InputGlyphCount']; $r++) { + $Rule['Input'][$r] = $this->read_ushort(); + } + $Rule['LookaheadGlyphCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['LookaheadGlyphCount']; $r++) { + $Rule['Lookahead'][$r] = $this->read_ushort(); + } + $Rule['SubstCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['SubstCount']; $r++) { + $Rule['SequenceIndex'][$r] = $this->read_ushort(); + $Rule['LookupListIndex'][$r] = $this->read_ushort(); + } + + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b] = $Rule; + } + } + } + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + else { + if ($SubstFormat == 3) { + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageBacktrackGlyphs'][] = implode("|", $glyphs); + } + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs'][] = implode("|", $glyphs); + // Don't use above value as these are ordered numerically not as need to process + } + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageLookahead'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageLookaheadGlyphs'][] = implode("|", $glyphs); + } + } + } + } + } + } + } + } + } + } + } + } + + //===================================================================================== + //===================================================================================== + //===================================================================================== + + $st = $this->mpdf->OTLscript; + $t = $this->mpdf->OTLlang; + $langsys = $gsub[$st][$t]; + + $lul = []; // array of LookupListIndexes + $tags = []; // corresponding array of feature tags e.g. 'ccmp' + foreach ($langsys as $tag => $ft) { + foreach ($ft as $ll) { + $lul[$ll] = $tag; + } + } + ksort($lul); // Order the Lookups in the order they are in the GUSB table, regardless of Feature order + $this->_getGSUBarray($Lookup, $lul, $st); +//print_r($lul); exit; + } + +//print_r($Lookup); exit; + + return [$GSUBScriptLang, $gsub, $GSLookup, $rtlPUAstr, $rtlPUAarr]; + } + +///////////////////////////////////////////////////////////////////////////////////////// + // GSUB functions + function _getGSUBarray(&$Lookup, &$lul, $scripttag, $level = 1, $coverage = '', $exB = '', $exL = '') + { + // Process (3) LookupList for specific Script-LangSys + // Generate preg_replace + $html = ''; + if ($level == 1) { + $html .= '<bookmark level="0" content="GSUB features">'; + } + foreach ($lul as $i => $tag) { + $html .= '<div class="level' . $level . '">'; + $html .= '<h5 class="level' . $level . '">'; + if ($level == 1) { + $html .= '<bookmark level="1" content="' . $tag . ' [#' . $i . ']">'; + } + $html .= 'Lookup #' . $i . ' [tag: <span style="color:#000066;">' . $tag . '</span>]</h5>'; + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + if ($ignore) { + $html .= '<div class="ignore">Ignoring: ' . $ignore . '</div> '; + } + + $Type = $Lookup[$i]['Type']; + $Flag = $Lookup[$i]['Flag']; + if (($Flag & 0x0001) == 1) { + $dir = 'RTL'; + } else { + $dir = 'LTR'; + } + + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $html .= '<div class="subtable">Subtable #' . $c; + if ($level == 1) { + $html .= '<bookmark level="2" content="Subtable #' . $c . '">'; + } + $html .= '</div>'; + + $SubstFormat = $Lookup[$i]['Subtable'][$c]['Format']; + + // LookupType 1: Single Substitution Subtable + if ($Lookup[$i]['Type'] == 1) { + $html .= '<div class="lookuptype">LookupType 1: Single Substitution Subtable</div>'; + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + if ($level == 2 && strpos($coverage, $inputGlyphs[0]) === false) { + continue; + } + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($inputGlyphs[0]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed"> ' . $this->formatEntity($substitute) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  <span class="unicode">' . $this->formatUni($substitute) . '</span> '; + $html .= '</div>'; + } + } // LookupType 2: Multiple Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 2) { + $html .= '<div class="lookuptype">LookupType 2: Multiple Substitution Subtable</div>'; + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute']; + if ($level == 2 && strpos($coverage, $inputGlyphs[0]) === false) { + continue; + } + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($inputGlyphs[0]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed"> ' . $this->formatEntityArr($substitute) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  <span class="unicode">' . $this->formatUniArr($substitute) . '</span> '; + $html .= '</div>'; + } + } // LookupType 3: Alternate Forms + else { + if ($Lookup[$i]['Type'] == 3) { + $html .= '<div class="lookuptype">LookupType 3: Alternate Forms</div>'; + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + if ($level == 2 && strpos($coverage, $inputGlyphs[0]) === false) { + continue; + } + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($inputGlyphs[0]) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($inputGlyphs[0]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed"> ' . $this->formatEntity($substitute) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  <span class="unicode">' . $this->formatUni($substitute) . '</span> '; + if (count($Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute']) > 1) { + for ($alt = 1; $alt < count($Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute']); $alt++) { + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][$alt]; + $html .= '  |   ALT #' . $alt . '   '; + $html .= '<span class="changed"> ' . $this->formatEntity($substitute) . '</span>'; + $html .= '  <span class="unicode">' . $this->formatUni($substitute) . '</span> '; + } + } + $html .= '</div>'; + } + } // LookupType 4: Ligature Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 4) { + $html .= '<div class="lookuptype">LookupType 4: Ligature Substitution Subtable</div>'; + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + if ($level == 2 && strpos($coverage, $inputGlyphs[0]) === false) { + continue; + } + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUniArr($inputGlyphs) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntityArr($inputGlyphs) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed"> ' . $this->formatEntity($substitute) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  <span class="unicode">' . $this->formatUni($substitute) . '</span> '; + $html .= '</div>'; + } + } // LookupType 5: Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 5) { + $html .= '<div class="lookuptype">LookupType 5: Contextual Substitution Subtable</div>'; + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $html .= '<div class="lookuptypesub">Format 1: Context Substitution</div>'; + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubRuleSetCount']; $s++) { + // SubRuleSet + $subRule = []; + $html .= '<div class="rule">Subrule Set: ' . $s . '</div>'; + foreach ($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'] as $rctr => $rule) { + // SubRule + $html .= '<div class="rule">SubRule: ' . $rctr . '</div>'; + $inputGlyphs = []; + if ($rule['GlyphCount'] > 1) { + $inputGlyphs = $rule['InputGlyphs']; + } + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['FirstGlyph']; + ksort($inputGlyphs); + $nInput = count($inputGlyphs); + + $exampleI = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + $html .= '</div>'; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $rule['SubstLookupRecord'][$b]['SequenceIndex']; + + // GENERATE exampleI[<seqIndex] .... exampleI[>seqIndex] + $exB = ''; + $exL = ''; + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + $exB .= $this->formatEntity($inputGlyphs[$ip]) . '‍'; + } + $exB .= '</span>'; + } + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + $exL .= $this->formatEntity($inputGlyphs[$ip]) . '‍'; + } + $exL .= '</span>'; + } + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } // Format 2: Class-based Context Glyph Substitution + else { + if ($SubstFormat == 2) { + $html .= '<div class="lookuptypesub">Format 2: Class-based Context Glyph Substitution</div>'; + foreach ($Lookup[$i]['Subtable'][$c]['SubClassSet'] as $inputClass => $cscs) { + $html .= '<div class="rule">Input Class: ' . $inputClass . '</div>'; + for ($cscrule = 0; $cscrule < $cscs['SubClassRuleCnt']; $cscrule++) { + $html .= '<div class="rule">Rule: ' . $cscrule . '</div>'; + $rule = $cscs['SubClassRule'][$cscrule]; + + $inputGlyphs = []; + + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + + if ($rule['InputGlyphCount'] > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $rule['InputGlyphCount']; $gcl++) { + $classindex = $rule['Input'][$gcl]; + $inputGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex]; + } + } + + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = implode('|', $Lookup[$i]['Subtable'][$c]['InputClasses']); + + $exampleI = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + if (!$inputGlyphs[$ff]) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> [NOT ' . $this->formatEntityStr($class0excl) . '] </span></div>'; + $exampleI[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']'; + } else { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + } + $html .= '</div>'; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // GENERATE exampleI[<seqIndex] .... exampleI[>seqIndex] + $exB = ''; + $exL = ''; + + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + if (!$inputGlyphs[$ip]) { + $exB .= '[*]'; + } else { + $exB .= $this->formatEntityFirst($inputGlyphs[$ip]) . '‍'; + } + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + if (!$inputGlyphs[$ip]) { + $exL .= '[*]'; + } else { + $exL .= $this->formatEntityFirst($inputGlyphs[$ip]) . '‍'; + } + } + $exL .= '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } // Format 3: Coverage-based Context Glyph Substitution p259 + else { + if ($SubstFormat == 3) { + $html .= '<div class="lookuptypesub">Format 3: Coverage-based Context Glyph Substitution </div>'; + // IgnoreMarks flag set on main Lookup table + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs']; + $CoverageInputGlyphs = implode('|', $inputGlyphs); + $nInput = $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; + + $exampleI = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + $html .= '</div>'; + + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $lup = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex']; + // GENERATE exampleI[<seqIndex] .... exampleI[>seqIndex] + $exB = ''; + $exL = ''; + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + $exB .= $exampleI[$ip] . '‍'; + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + $exL .= $exampleI[$ip] . '‍'; + } + $exL .= '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } + +//print_r($Lookup[$i]); +//print_r($volt[(count($volt)-1)]); exit; + } // LookupType 6: Chaining Contextual Substitution Subtable + else { + if ($Lookup[$i]['Type'] == 6) { + $html .= '<div class="lookuptype">LookupType 6: Chaining Contextual Substitution Subtable</div>'; + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $html .= '<div class="lookuptypesub">Format 1: Simple Chaining Context Glyph Substitution </div>'; + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; $s++) { + // ChainSubRuleSet + $subRule = []; + $html .= '<div class="rule">Subrule Set: ' . $s . '</div>'; + $firstInputGlyph = $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'][$s]; // First input gyyph + foreach ($Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'] as $rctr => $rule) { + $html .= '<div class="rule">SubRule: ' . $rctr . '</div>'; + // ChainSubRule + $inputGlyphs = []; + if ($rule['InputGlyphCount'] > 1) { + $inputGlyphs = $rule['InputGlyphs']; + } + $inputGlyphs[0] = $firstInputGlyph; + ksort($inputGlyphs); + $nInput = count($inputGlyphs); + + if ($rule['BacktrackGlyphCount']) { + $backtrackGlyphs = $rule['BacktrackGlyphs']; + } else { + $backtrackGlyphs = []; + } + + if ($rule['LookaheadGlyphCount']) { + $lookaheadGlyphs = $rule['LookaheadGlyphs']; + } else { + $lookaheadGlyphs = []; + } + + $exampleB = []; + $exampleI = []; + $exampleL = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) { + $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>'; + $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]); + } + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + for ($ff = 0; $ff < count($lookaheadGlyphs); $ff++) { + $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>'; + $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]); + } + $html .= '</div>'; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // GENERATE exampleB[n] exampleI[<seqIndex] .... exampleI[>seqIndex] exampleL[n] + $exB = ''; + $exL = ''; + if (count($exampleB)) { + $exB .= '<span class="backtrack">' . implode('‍', $exampleB) . '</span>'; + } + + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + $exB .= $this->formatEntity($inputGlyphs[$ip]) . '‍'; + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + $exL .= $this->formatEntity($inputGlyphs[$ip]) . '‍'; + } + $exL .= '</span>'; + } + + if (count($exampleL)) { + $exL .= '<span class="lookahead">' . implode('‍', $exampleL) . '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + else { + if ($SubstFormat == 2) { + $html .= '<div class="lookuptypesub">Format 2: Class-based Chaining Context Glyph Substitution </div>'; + foreach ($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'] as $inputClass => $cscs) { + $html .= '<div class="rule">Input Class: ' . $inputClass . '</div>'; + for ($cscrule = 0; $cscrule < $cscs['ChainSubClassRuleCnt']; $cscrule++) { + $html .= '<div class="rule">Rule: ' . $cscrule . '</div>'; + $rule = $cscs['ChainSubClassRule'][$cscrule]; + + // These contain classes of glyphs as strings + // $Lookup[$i]['Subtable'][$c]['InputClasses'][(class)] e.g. 02E6|02E7|02E8 + // $Lookup[$i]['Subtable'][$c]['LookaheadClasses'][(class)] + // $Lookup[$i]['Subtable'][$c]['BacktrackClasses'][(class)] + // These contain arrays of classIndexes + // [Backtrack] [Lookahead] and [Input] (Input is from the second position only) + + $inputGlyphs = []; + + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + if ($rule['InputGlyphCount'] > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $rule['InputGlyphCount']; $gcl++) { + $classindex = $rule['Input'][$gcl]; + $inputGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex]; + } + } + // Class 0 contains all the glyphs NOT in the other classes + $class0excl = implode('|', $Lookup[$i]['Subtable'][$c]['InputClasses']); + + $nInput = $rule['InputGlyphCount']; + + if ($rule['BacktrackGlyphCount']) { + for ($gcl = 0; $gcl < $rule['BacktrackGlyphCount']; $gcl++) { + $classindex = $rule['Backtrack'][$gcl]; + $backtrackGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['BacktrackClasses'][$classindex]; + } + } else { + $backtrackGlyphs = []; + } + + if ($rule['LookaheadGlyphCount']) { + for ($gcl = 0; $gcl < $rule['LookaheadGlyphCount']; $gcl++) { + $classindex = $rule['Lookahead'][$gcl]; + $lookaheadGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['LookaheadClasses'][$classindex]; + } + } else { + $lookaheadGlyphs = []; + } + + $exampleB = []; + $exampleI = []; + $exampleL = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) { + if (!$backtrackGlyphs[$ff]) { + $html .= '<div>Backtrack #' . $ff . ': <span class="unchanged"> [NOT ' . $this->formatEntityStr($class0excl) . '] </span></div>'; + $exampleB[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']'; + } else { + $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>'; + $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]); + } + } + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + if (!$inputGlyphs[$ff]) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> [NOT ' . $this->formatEntityStr($class0excl) . '] </span></div>'; + $exampleI[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']'; + } else { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + } + for ($ff = 0; $ff < count($lookaheadGlyphs); $ff++) { + if (!$lookaheadGlyphs[$ff]) { + $html .= '<div>Lookahead #' . $ff . ': <span class="unchanged"> [NOT ' . $this->formatEntityStr($class0excl) . '] </span></div>'; + $exampleL[] = '[NOT ' . $this->formatEntityFirst($class0excl) . ']'; + } else { + $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>'; + $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]); + } + } + $html .= '</div>'; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // GENERATE exampleB[n] exampleI[<seqIndex] .... exampleI[>seqIndex] exampleL[n] + $exB = ''; + $exL = ''; + if (count($exampleB)) { + $exB .= '<span class="backtrack">' . implode('‍', $exampleB) . '</span>'; + } + + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + if (!$inputGlyphs[$ip]) { + $exB .= '[*]'; + } else { + $exB .= $this->formatEntityFirst($inputGlyphs[$ip]) . '‍'; + } + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + if (!$inputGlyphs[$ip]) { + $exL .= '[*]'; + } else { + $exL .= $this->formatEntityFirst($inputGlyphs[$ip]) . '‍'; + } + } + $exL .= '</span>'; + } + + if (count($exampleL)) { + $exL .= '<span class="lookahead">' . implode('‍', $exampleL) . '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + } + } + +//print_r($Lookup[$i]['Subtable'][$c]); exit; + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + else { + if ($SubstFormat == 3) { + $html .= '<div class="lookuptypesub">Format 3: Coverage-based Chaining Context Glyph Substitution </div>'; + // IgnoreMarks flag set on main Lookup table + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs']; + $CoverageInputGlyphs = implode('|', $inputGlyphs); + $nInput = $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; + + if ($Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']) { + $backtrackGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageBacktrackGlyphs']; + } else { + $backtrackGlyphs = []; + } + + if ($Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']) { + $lookaheadGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageLookaheadGlyphs']; + } else { + $lookaheadGlyphs = []; + } + + $exampleB = []; + $exampleI = []; + $exampleL = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) { + $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>'; + $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]); + } + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + for ($ff = 0; $ff < count($lookaheadGlyphs); $ff++) { + $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>'; + $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]); + } + $html .= '</div>'; + + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $lup = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex']; + + // GENERATE exampleB[n] exampleI[<seqIndex] .... exampleI[>seqIndex] exampleL[n] + $exB = ''; + $exL = ''; + if (count($exampleB)) { + $exB .= '<span class="backtrack">' . implode('‍', $exampleB) . '</span>'; + } + + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + $exB .= $exampleI[$ip] . '‍'; + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + $exL .= $exampleI[$ip] . '‍'; + } + $exL .= '</span>'; + } + + if (count($exampleL)) { + $exL .= '<span class="lookahead">' . implode('‍', $exampleL) . '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGSUBarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + } + } + } + } + } + } + } + } + } + } + $html .= '</div>'; + } + if ($level == 1) { + $this->mpdf->WriteHTML($html); + } else { + return $html; + } +//print_r($Lookup); exit; + } + + //===================================================================================== + //===================================================================================== + // mPDF 5.7.1 + function _checkGSUBignore($flag, $glyph, $MarkFilteringSet) + { + $ignore = false; + // Flag & 0x0008 = Ignore Marks + if ((($flag & 0x0008) == 0x0008) && strpos($this->GlyphClassMarks, $glyph)) { + $ignore = true; + } + if ((($flag & 0x0004) == 0x0004) && strpos($this->GlyphClassLigatures, $glyph)) { + $ignore = true; + } + if ((($flag & 0x0002) == 0x0002) && strpos($this->GlyphClassBases, $glyph)) { + $ignore = true; + } + // Flag & 0xFF?? = MarkAttachmentType + if (($flag & 0xFF00) && strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) { + $ignore = true; + } + // Flag & 0x0010 = UseMarkFilteringSet + if (($flag & 0x0010) && strpos($this->MarkGlyphSets[$MarkFilteringSet], $glyph)) { + $ignore = true; + } + + return $ignore; + } + + function _getGSUBignoreString($flag, $MarkFilteringSet) + { + // If ignoreFlag set, combine all ignore glyphs into -> "((?:(?: FBA1| FBA2| FBA3))*)" + // else "()" + // for Input - set on secondary Lookup table if in Context, and set Backtrack and Lookahead on Context Lookup + $str = ""; + $ignoreflag = 0; + + // Flag & 0xFF?? = MarkAttachmentType + if ($flag & 0xFF00) { + $MarkAttachmentType = $flag >> 8; + $ignoreflag = $flag; + //$str = $this->MarkAttachmentType[$MarkAttachmentType]; + $str = "MarkAttachmentType[" . $MarkAttachmentType . "] "; + } + + // Flag & 0x0010 = UseMarkFilteringSet + if ($flag & 0x0010) { + throw new \Mpdf\Exception\FontException("This font " . $this->fontkey . " contains MarkGlyphSets"); + $str = "Mark Glyph Set: "; + $str .= $this->MarkGlyphSets[$MarkFilteringSet]; + } + + // If Ignore Marks set, supercedes any above + // Flag & 0x0008 = Ignore Marks + if (($flag & 0x0008) == 0x0008) { + $ignoreflag = 8; + //$str = $this->GlyphClassMarks; + $str = "Mark Glyphs "; + } + + // Flag & 0x0004 = Ignore Ligatures + if (($flag & 0x0004) == 0x0004) { + $ignoreflag += 4; + if ($str) { + $str .= "|"; + } + //$str .= $this->GlyphClassLigatures; + $str .= "Ligature Glyphs "; + } + // Flag & 0x0002 = Ignore BaseGlyphs + if (($flag & 0x0002) == 0x0002) { + $ignoreflag += 2; + if ($str) { + $str .= "|"; + } + //$str .= $this->GlyphClassBases; + $str .= "Base Glyphs "; + } + if ($str) { + return $str; + } else { + return ""; + } + } + + // GSUB Patterns + + /* + BACKTRACK INPUT LOOKAHEAD + ================================== ================== ================================== + (FEEB|FEEC)(ign) ¦(FD12|FD13)(ign) ¦(0612)¦(ign) (0613)¦(ign) (FD12|FD13)¦(ign) (FEEB|FEEC) + ---------------- ---------------- ----- ------------ --------------- --------------- + Backtrack 1 Backtrack 2 Input 1 Input 2 Lookahead 1 Lookahead 2 + -------- --- --------- --- ---- --- ---- --- --------- --- ------- + \${1} \${2} \${3} \${4} \${5+} \${6+} \${7+} \${8+} + + nBacktrack = 2 nInput = 2 nLookahead = 2 + + nBsubs = 2xnBack nIsubs = (nBsubs+) nLsubs = (nBsubs+nIsubs+) 2xnLookahead + "\${1}\${2} " (nInput*2)-1 "\${5+} \${6+}" + "REPL" + + ¦\${1}\${2} ¦\${3}\${4} ¦REPL¦\${5+} \${6+}¦\${7+} \${8+}¦ + + + INPUT nInput = 5 + ============================================================ + ¦(0612)¦(ign) (0613)¦(ign) (0614)¦(ign) (0615)¦(ign) (0615)¦ + \${1} \${2} \${3} \${4} \${5} \${6} \${7} \${8} \${9} (All backreference numbers are + nBsubs) + ----- ------------ ------------ ------------ ------------ + Input 1 Input 2 Input 3 Input 4 Input 5 + + A====== SequenceIndex=1 ; Lookup match nGlyphs=1 + B=================== SequenceIndex=1 ; Lookup match nGlyphs=2 + C=============================== SequenceIndex=1 ; Lookup match nGlyphs=3 + D======================= SequenceIndex=2 ; Lookup match nGlyphs=2 + E===================================== SequenceIndex=2 ; Lookup match nGlyphs=3 + F====================== SequenceIndex=4 ; Lookup match nGlyphs=2 + + All backreference numbers are + nBsubs + A - "REPL\${2} \${3}\${4} \${5}\${6} \${7}\${8} \${9}" + B - "REPL\${2}\${4} \${5}\${6} \${7}\${8} \${9}" + C - "REPL\${2}\${4}\${6} \${7}\${8} \${9}" + D - "\${1} REPL\${2}\${4}\${6} \${7}\${8} \${9}" + E - "\${1} REPL\${2}\${4}\${6}\${8} \${9}" + F - "\${1}\${2} \${3}\${4} \${5} REPL\${6}\${8}" + */ + + function _makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + // $inputGlyphs = array of glyphs(glyphstrings) making up Input sequence in Context + // $lookupGlyphs = array of glyphs (single Glyphs) making up Lookup Input sequence + $mLen = count($lookupGlyphs); // nGlyphs in the secondary Lookup match + $nInput = count($inputGlyphs); // nGlyphs in the Primary Input sequence + $str = ""; + for ($i = 0; $i < $nInput; $i++) { + if ($i > 0) { + $str .= $ignore . " "; + } + if ($i >= $seqIndex && $i < ($seqIndex + $mLen)) { + $str .= "" . $lookupGlyphs[($i - $seqIndex)] . ""; + } else { + $str .= "" . $inputGlyphs[($i)] . ""; + } + } + + return $str; + } + + function _makeGSUBinputMatch($inputGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + // $inputGlyphs = array of glyphs(glyphstrings) making up Input sequence in Context + // $lookupGlyphs = array of glyphs making up Lookup Input sequence - if applicable + $str = ""; + for ($i = 1; $i <= count($inputGlyphs); $i++) { + if ($i > 1) { + $str .= $ignore . " "; + } + $str .= "" . $inputGlyphs[($i - 1)] . ""; + } + + return $str; + } + + function _makeGSUBbacktrackMatch($backtrackGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(FEEB|FEEC)(ignore) ¦(FD12|FD13)(ignore) ¦ + // $backtrackGlyphs = array of glyphstrings making up Backtrack sequence + // 3 2 1 0 + // each item being e.g. E0AD|E0AF|F1FD + $str = ""; + for ($i = (count($backtrackGlyphs) - 1); $i >= 0; $i--) { + $str .= "" . $backtrackGlyphs[$i] . " " . $ignore . " "; + } + + return $str; + } + + function _makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(ignore) (FD12|FD13)¦(ignore) (FEEB|FEEC)¦ + // $lookaheadGlyphs = array of glyphstrings making up Lookahead sequence + // 0 1 2 3 + // each item being e.g. E0AD|E0AF|F1FD + $str = ""; + for ($i = 0; $i < count($lookaheadGlyphs); $i++) { + $str .= $ignore . " " . $lookaheadGlyphs[$i] . ""; + } + + return $str; + } + + function _makeGSUBinputReplacement($nInput, $REPL, $ignore, $nBsubs, $mLen, $seqIndex) + { + // Returns e.g. "REPL\${6}\${8}" or "\${1}\${2} \${3} REPL\${4}\${6}\${8} \${9}" + // $nInput nGlyphs in the Primary Input sequence + // $REPL replacement glyphs from secondary lookup + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // $nBsubs Number of Backtrack substitutions (= 2x Number of Backtrack glyphs) + // $mLen nGlyphs in the secondary Lookup match - if no secondary lookup, should=$nInput + // $seqIndex Sequence Index to apply the secondary match + if ($ignore == "()") { + $ign = false; + } else { + $ign = true; + } + $str = ""; + if ($nInput == 1) { + $str = $REPL; + } else { + if ($nInput > 1) { + if ($mLen == $nInput) { // whole string replaced + $str = $REPL; + if ($ign) { + // for every nInput over 1, add another replacement backreference, to move IGNORES after replacement + for ($x = 2; $x <= $nInput; $x++) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + } + } else { // if only part of string replaced: + for ($x = 1; $x < ($seqIndex + 1); $x++) { + if ($x == 1) { + $str .= '\\' . ($nBsubs + 1); + } else { + if ($ign) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1))); + } + } + if ($seqIndex > 0) { + $str .= " "; + } + $str .= $REPL; + if ($ign) { + for ($x = (max(($seqIndex + 1), 2)); $x < ($seqIndex + 1 + $mLen); $x++) { // move IGNORES after replacement + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + } + for ($x = ($seqIndex + 1 + $mLen); $x <= $nInput; $x++) { + if ($ign) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1))); + } + } + } + } + + return $str; + } + + ////////////////////////////////////////////////////////////////////////////////// + function _getCoverage($convert2hex = true) + { + $g = []; + $CoverageFormat = $this->read_ushort(); + if ($CoverageFormat == 1) { + $CoverageGlyphCount = $this->read_ushort(); + for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) { + $glyphID = $this->read_ushort(); + if ($convert2hex) { + $g[] = unicode_hex($this->glyphToChar[$glyphID][0]); + } else { + $g[] = $glyphID; + } + } + } + if ($CoverageFormat == 2) { + $RangeCount = $this->read_ushort(); + for ($r = 0; $r < $RangeCount; $r++) { + $start = $this->read_ushort(); + $end = $this->read_ushort(); + $StartCoverageIndex = $this->read_ushort(); // n/a + for ($gid = $start; $gid <= $end; $gid++) { + $glyphID = $gid; + if ($convert2hex) { + $g[] = unicode_hex($this->glyphToChar[$glyphID][0]); + } else { + $g[] = $glyphID; + } + } + } + } + + return $g; + } + + ////////////////////////////////////////////////////////////////////////////////// + function _getClasses($offset) + { + $this->seek($offset); + $ClassFormat = $this->read_ushort(); + $GlyphByClass = []; + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $startGlyphID = $StartGlyph + $i; + $endGlyphID = $StartGlyph + $i; + $class = $this->read_ushort(); + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if ($this->glyphToChar[$g][0]) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]); + } + } + } + } else { + if ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $startGlyphID = $this->read_ushort(); + $endGlyphID = $this->read_ushort(); + $class = $this->read_ushort(); + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if ($this->glyphToChar[$g][0]) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]); + } + } + } + } + } + $gbc = []; + foreach ($GlyphByClass as $class => $garr) { + $gbc[$class] = implode('|', $garr); + } + + return $gbc; + } + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + function _getGPOStables() + { + /////////////////////////////////// + // GPOS - Glyph Positioning + /////////////////////////////////// + if (isset($this->tables["GPOS"])) { + $this->mpdf->WriteHTML('<h1>GPOS Tables</h1>'); + $ffeats = []; + $gpos_offset = $this->seek_table("GPOS"); + $this->skip(4); + $ScriptList_offset = $gpos_offset + $this->read_ushort(); + $FeatureList_offset = $gpos_offset + $this->read_ushort(); + $LookupList_offset = $gpos_offset + $this->read_ushort(); + + // ScriptList + $this->seek($ScriptList_offset); + $ScriptCount = $this->read_ushort(); + for ($i = 0; $i < $ScriptCount; $i++) { + $ScriptTag = $this->read_tag(); // = "beng", "deva" etc. + $ScriptTableOffset = $this->read_ushort(); + $ffeats[$ScriptTag] = $ScriptList_offset + $ScriptTableOffset; + } + + // Script Table + foreach ($ffeats as $t => $o) { + $ls = []; + $this->seek($o); + $DefLangSys_offset = $this->read_ushort(); + if ($DefLangSys_offset > 0) { + $ls['DFLT'] = $DefLangSys_offset + $o; + } + $LangSysCount = $this->read_ushort(); + for ($i = 0; $i < $LangSysCount; $i++) { + $LangTag = $this->read_tag(); // = + $LangTableOffset = $this->read_ushort(); + $ls[$LangTag] = $o + $LangTableOffset; + } + $ffeats[$t] = $ls; + } + + // Get FeatureIndexList + // LangSys Table - from first listed langsys + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = []; + $langsystable_offset = $o; + $this->seek($langsystable_offset); + $LookUpOrder = $this->read_ushort(); //==NULL + $ReqFeatureIndex = $this->read_ushort(); + if ($ReqFeatureIndex != 0xFFFF) { + $FeatureIndex[] = $ReqFeatureIndex; + } + $FeatureCount = $this->read_ushort(); + for ($i = 0; $i < $FeatureCount; $i++) { + $FeatureIndex[] = $this->read_ushort(); // = index of feature + } + $ffeats[$st][$t] = $FeatureIndex; + } + } +//print_r($ffeats); exit; + // Feauture List => LookupListIndex es + $this->seek($FeatureList_offset); + $FeatureCount = $this->read_ushort(); + $Feature = []; + for ($i = 0; $i < $FeatureCount; $i++) { + $Feature[$i] = ['tag' => $this->read_tag()]; + $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort(); + } + for ($i = 0; $i < $FeatureCount; $i++) { + $this->seek($Feature[$i]['offset']); + $this->read_ushort(); // null + $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort(); + $Feature[$i]['LookupListIndex'] = []; + for ($c = 0; $c < $Lookupcount; $c++) { + $Feature[$i]['LookupListIndex'][] = $this->read_ushort(); + } + } + + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = $ffeats[$st][$t]; + foreach ($FeatureIndex as $k => $fi) { + $ffeats[$st][$t][$k] = $Feature[$fi]; + } + } + } +//print_r($ffeats); exit; + //===================================================================================== + $gpos = []; + $GPOSScriptLang = []; + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $langsys) { + $lg = []; + foreach ($langsys as $ft) { + $lg[$ft['LookupListIndex'][0]] = $ft; + } + // list of Lookups in order they need to be run i.e. order listed in Lookup table + ksort($lg); + foreach ($lg as $ft) { + $gpos[$st][$t][$ft['tag']] = $ft['LookupListIndex']; + } + if (!isset($GPOSScriptLang[$st])) { + $GPOSScriptLang[$st] = ''; + } + $GPOSScriptLang[$st] .= $t . ' '; + } + } + if ($this->mode == 'summary') { + $this->mpdf->WriteHTML('<h3>GPOS Scripts & Languages</h3>'); + $html = ''; + if (count($gpos)) { + foreach ($gpos as $st => $g) { + $html .= '<h5>' . $st . '</h5>'; + foreach ($g as $l => $t) { + $html .= '<div><a href="font_dump_OTL.php?script=' . $st . '&lang=' . $l . '">' . $l . '</a></b>: '; + foreach ($t as $tag => $o) { + $html .= $tag . ' '; + } + $html .= '</div>'; + } + } + } else { + $html .= '<div>No entries in GPOS table.</div>'; + } + $this->mpdf->WriteHTML($html); + $this->mpdf->WriteHTML('</div>'); + + return 0; + } + + //===================================================================================== + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $Lookup = []; + $Offsets = []; + $SubtableCount = []; + for ($i = 0; $i < $LookupCount; $i++) { + $Offsets[$i] = $LookupList_offset + $this->read_ushort(); + } + for ($i = 0; $i < $LookupCount; $i++) { + $this->seek($Offsets[$i]); + $Lookup[$i]['Type'] = $this->read_ushort(); + $Lookup[$i]['Flag'] = $flag = $this->read_ushort(); + $Lookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort(); + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $Lookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort(); + } + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) == 0x0010) { + $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } + // else { $Lookup[$i]['MarkFilteringSet'] = ''; } + // Lookup Type 9: Extension + if ($Lookup[$i]['Type'] == 9) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $this->seek($Lookup[$i]['Subtables'][$c]); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $Lookup[$i]['Subtables'][$c] = $Lookup[$i]['Subtables'][$c] + $this->read_ulong(); + } + $Lookup[$i]['Type'] = $type; + } + } + + //===================================================================================== + + $st = $this->mpdf->OTLscript; + $t = $this->mpdf->OTLlang; + $langsys = $gpos[$st][$t]; + + $lul = []; // array of LookupListIndexes + $tags = []; // corresponding array of feature tags e.g. 'ccmp' + if (count($langsys)) { + foreach ($langsys as $tag => $ft) { + foreach ($ft as $ll) { + $lul[$ll] = $tag; + } + } + } + ksort($lul); // Order the Lookups in the order they are in the GUSB table, regardless of Feature order + $this->_getGPOSarray($Lookup, $lul, $st); + +//print_r($lul); exit; + + return [$GPOSScriptLang, $gpos, $Lookup]; + } // end if GPOS + } + + ////////////////////////////////////////////////////////////////////////////////// + //===================================================================================== + //===================================================================================== + //===================================================================================== +///////////////////////////////////////////////////////////////////////////////////////// + // GPOS functions + function _getGPOSarray(&$Lookup, $lul, $scripttag, $level = 1, $lcoverage = '', $exB = '', $exL = '') + { + // Process (3) LookupList for specific Script-LangSys + $html = ''; + if ($level == 1) { + $html .= '<bookmark level="0" content="GPOS features">'; + } + foreach ($lul as $luli => $tag) { + $html .= '<div class="level' . $level . '">'; + $html .= '<h5 class="level' . $level . '">'; + if ($level == 1) { + $html .= '<bookmark level="1" content="' . $tag . ' [#' . $luli . ']">'; + } + $html .= 'Lookup #' . $luli . ' [tag: <span style="color:#000066;">' . $tag . '</span>]</h5>'; + $ignore = $this->_getGSUBignoreString($Lookup[$luli]['Flag'], $Lookup[$luli]['MarkFilteringSet']); + if ($ignore) { + $html .= '<div class="ignore">Ignoring: ' . $ignore . '</div> '; + } + + $Type = $Lookup[$luli]['Type']; + $Flag = $Lookup[$luli]['Flag']; + if (($Flag & 0x0001) == 1) { + $dir = 'RTL'; + } else { + $dir = 'LTR'; + } + + for ($c = 0; $c < $Lookup[$luli]['SubtableCount']; $c++) { + $html .= '<div class="subtable">Subtable #' . $c; + if ($level == 1) { + $html .= '<bookmark level="2" content="Subtable #' . $c . '">'; + } + $html .= '</div>'; + + // Lets start + $subtable_offset = $Lookup[$luli]['Subtables'][$c]; + $this->seek($subtable_offset); + $PosFormat = $this->read_ushort(); + + //////////////////////////////////////////////////////////////////////////////// + // LookupType 1: Single adjustment Adjust position of a single glyph (e.g. SmallCaps/Sups/Subs) + //////////////////////////////////////////////////////////////////////////////// + if ($Lookup[$luli]['Type'] == 1) { + $html .= '<div class="lookuptype">LookupType 1: Single adjustment [Format ' . $PosFormat . ']</div>'; + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat = $this->read_ushort(); + $Value = $this->_getValueRecord($ValueFormat); + + $this->seek($Coverage); + $glyphs = $this->_getCoverage(); // Array of Hex Glyphs + for ($g = 0; $g < count($glyphs); $g++) { + if ($level == 2 && strpos($lcoverage, $glyphs[$g]) === false) { + continue; + } + + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($glyphs[$g]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;"> ' . $this->formatEntity($glyphs[$g]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= ' <span class="unicode">'; + if ($Value['XPlacement']) { + $html .= ' Xpl: ' . $Value['XPlacement'] . ';'; + } + if ($Value['YPlacement']) { + $html .= ' YPl: ' . $Value['YPlacement'] . ';'; + } + if ($Value['XAdvance']) { + $html .= ' Xadv: ' . $Value['XAdvance']; + } + $html .= '</span>'; + $html .= '</div>'; + } + } //=========== + // Format 2: + //=========== + else { + if ($PosFormat == 2) { + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat = $this->read_ushort(); + $ValueCount = $this->read_ushort(); + $Values = []; + for ($v = 0; $v < $ValueCount; $v++) { + $Values[] = $this->_getValueRecord($ValueFormat); + } + + $this->seek($Coverage); + $glyphs = $this->_getCoverage(); // Array of Hex Glyphs + + for ($g = 0; $g < count($glyphs); $g++) { + if ($level == 2 && strpos($lcoverage, $glyphs[$g]) === false) { + continue; + } + $Value = $Values[$g]; + + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($glyphs[$g]) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($glyphs[$g]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;"> ' . $this->formatEntity($glyphs[$g]) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= ' <span class="unicode">'; + if ($Value['XPlacement']) { + $html .= ' Xpl: ' . $Value['XPlacement'] . ';'; + } + if ($Value['YPlacement']) { + $html .= ' YPl: ' . $Value['YPlacement'] . ';'; + } + if ($Value['XAdvance']) { + $html .= ' Xadv: ' . $Value['XAdvance']; + } + $html .= '</span>'; + $html .= '</div>'; + } + } + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 2: Pair adjustment Adjust position of a pair of glyphs (Kerning) + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 2) { + $html .= '<div class="lookuptype">LookupType 2: Pair adjustment e.g. Kerning [Format ' . $PosFormat . ']</div>'; + $Coverage = $subtable_offset + $this->read_ushort(); + $ValueFormat1 = $this->read_ushort(); + $ValueFormat2 = $this->read_ushort(); + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + $PairSetCount = $this->read_ushort(); + $PairSetOffset = []; + for ($p = 0; $p < $PairSetCount; $p++) { + $PairSetOffset[] = $subtable_offset + $this->read_ushort(); + } + $this->seek($Coverage); + $glyphs = $this->_getCoverage(); // Array of Hex Glyphs + for ($p = 0; $p < $PairSetCount; $p++) { + if ($level == 2 && strpos($lcoverage, $glyphs[$p]) === false) { + continue; + } + $this->seek($PairSetOffset[$p]); + // First Glyph = $glyphs[$p] +// Takes too long e.g. Calibri font - just list kerning pairs with this: + $html .= '<div class="glyphs">'; + $html .= '<span class="unchanged"> ' . $this->formatEntity($glyphs[$p]) . ' </span>'; + + //PairSet table + $PairValueCount = $this->read_ushort(); + for ($pv = 0; $pv < $PairValueCount; $pv++) { + //PairValueRecord + $gid = $this->read_ushort(); + $SecondGlyph = unicode_hex($this->glyphToChar[$gid][0]); + $Value1 = $this->_getValueRecord($ValueFormat1); + $Value2 = $this->_getValueRecord($ValueFormat2); + + // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take + // account of direction. mPDF does not need the XPlacement adjustment + if ($dir == 'RTL' && $Value1['XPlacement']) { + $Value1['XPlacement'] -= $Value1['XAdvance']; + } + + if ($ValueFormat2) { + // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 to take + // account of direction. mPDF does not need the XPlacement adjustment + if ($dir == 'RTL' && $Value2['XPlacement'] && $Value2['XAdvance']) { + $Value2['XPlacement'] -= $Value2['XAdvance']; + } + } + + $html .= ' ' . $this->formatEntity($SecondGlyph) . ' '; + + /* + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">'.$this->formatUni($glyphs[$p]).' </span> '; + if ($level==2 && $exB) { $html .= $exB; } + $html .= '<span class="unchanged"> '.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>'; + if ($level==2 && $exL) { $html .= $exL; } + $html .= '  » »  '; + if ($level==2 && $exB) { $html .= $exB; } + $html .= '<span class="changed" style="font-feature-settings:\''.$tag.'\' 1;"> '.$this->formatEntity($glyphs[$p]).$this->formatEntity($SecondGlyph).'</span>'; + if ($level==2 && $exL) { $html .= $exL; } + $html .= ' <span class="unicode">'; + if ($Value1['XPlacement']) { $html .= ' Xpl[1]: '.$Value1['XPlacement'].';'; } + if ($Value1['YPlacement']) { $html .= ' YPl[1]: '.$Value1['YPlacement'].';'; } + if ($Value1['XAdvance']) { $html .= ' Xadv[1]: '.$Value1['XAdvance']; } + if ($Value2['XPlacement']) { $html .= ' Xpl[2]: '.$Value2['XPlacement'].';'; } + if ($Value2['YPlacement']) { $html .= ' YPl[2]: '.$Value2['YPlacement'].';'; } + if ($Value2['XAdvance']) { $html .= ' Xadv[2]: '.$Value2['XAdvance']; } + $html .= '</span>'; + $html .= '</div>'; + */ + } + $html .= '</div>'; + } + } //=========== + // Format 2: + //=========== + else { + if ($PosFormat == 2) { + $ClassDef1 = $subtable_offset + $this->read_ushort(); + $ClassDef2 = $subtable_offset + $this->read_ushort(); + $Class1Count = $this->read_ushort(); + $Class2Count = $this->read_ushort(); + + $sizeOfPair = (2 * $this->count_bits($ValueFormat1)) + (2 * $this->count_bits($ValueFormat2)); + $sizeOfValueRecords = $Class1Count * $Class2Count * $sizeOfPair; + + // NB Class1Count includes Class 0 even though it is not defined by $ClassDef1 + // i.e. Class1Count = 5; Class1 will contain array(indices 1-4); + $Class1 = $this->_getClassDefinitionTable($ClassDef1); + $Class2 = $this->_getClassDefinitionTable($ClassDef2); + + $this->seek($subtable_offset + 16); + + for ($i = 0; $i < $Class1Count; $i++) { + for ($j = 0; $j < $Class2Count; $j++) { + $Value1 = $this->_getValueRecord($ValueFormat1); + $Value2 = $this->_getValueRecord($ValueFormat2); + + // If RTL pairs, GPOS declares a XPlacement e.g. -180 for an XAdvance of -180 + // of direction. mPDF does not need the XPlacement adjustment + if ($dir == 'RTL' && $Value1['XPlacement'] && $Value1['XAdvance']) { + $Value1['XPlacement'] -= $Value1['XAdvance']; + } + if ($ValueFormat2) { + if ($dir == 'RTL' && $Value2['XPlacement'] && $Value2['XAdvance']) { + $Value2['XPlacement'] -= $Value2['XAdvance']; + } + } + + for ($c1 = 0; $c1 < count($Class1[$i]); $c1++) { + $FirstGlyph = $Class1[$i][$c1]; + if ($level == 2 && strpos($lcoverage, $FirstGlyph) === false) { + continue; + } + + for ($c2 = 0; $c2 < count($Class2[$j]); $c2++) { + $SecondGlyph = $Class2[$j][$c2]; + + if (!$Value1['XPlacement'] && !$Value1['YPlacement'] && !$Value1['XAdvance'] && !$Value2['XPlacement'] && !$Value2['YPlacement'] && !$Value2['XAdvance']) { + continue; + } + + $html .= '<div class="substitution">'; + $html .= '<span class="unicode">' . $this->formatUni($FirstGlyph) . ' </span> '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="unchanged"> ' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= '  » »  '; + if ($level == 2 && $exB) { + $html .= $exB; + } + $html .= '<span class="changed" style="font-feature-settings:\'' . $tag . '\' 1;"> ' . $this->formatEntity($FirstGlyph) . $this->formatEntity($SecondGlyph) . '</span>'; + if ($level == 2 && $exL) { + $html .= $exL; + } + $html .= ' <span class="unicode">'; + if ($Value1['XPlacement']) { + $html .= ' Xpl[1]: ' . $Value1['XPlacement'] . ';'; + } + if ($Value1['YPlacement']) { + $html .= ' YPl[1]: ' . $Value1['YPlacement'] . ';'; + } + if ($Value1['XAdvance']) { + $html .= ' Xadv[1]: ' . $Value1['XAdvance']; + } + if ($Value2['XPlacement']) { + $html .= ' Xpl[2]: ' . $Value2['XPlacement'] . ';'; + } + if ($Value2['YPlacement']) { + $html .= ' YPl[2]: ' . $Value2['YPlacement'] . ';'; + } + if ($Value2['XAdvance']) { + $html .= ' Xadv[2]: ' . $Value2['XAdvance']; + } + $html .= '</span>'; + $html .= '</div>'; + } + } + } + } + } + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 3: Cursive attachment Attach cursive glyphs + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 3) { + $html .= '<div class="lookuptype">LookupType 3: Cursive attachment </div>'; + $Coverage = $subtable_offset + $this->read_ushort(); + $EntryExitCount = $this->read_ushort(); + $EntryAnchors = []; + $ExitAnchors = []; + for ($i = 0; $i < $EntryExitCount; $i++) { + $EntryAnchors[$i] = $this->read_ushort(); + $ExitAnchors[$i] = $this->read_ushort(); + } + + $this->seek($Coverage); + $Glyphs = $this->_getCoverage(); + for ($i = 0; $i < $EntryExitCount; $i++) { + // Need default XAdvance for glyph + $pdfWidth = $this->mpdf->_getCharWidth($this->mpdf->fonts[$this->fontkey]['cw'], hexdec($Glyphs[$i])); + $EntryAnchor = $EntryAnchors[$i]; + $ExitAnchor = $ExitAnchors[$i]; + $html .= '<div class="glyphs">'; + $html .= '<span class="unchanged">' . $this->formatEntity($Glyphs[$i]) . ' </span> '; + $html .= '<span class="unicode"> ' . $this->formatUni($Glyphs[$i]) . ' => '; + + if ($EntryAnchor != 0) { + $EntryAnchor += $subtable_offset; + list($x, $y) = $this->_getAnchorTable($EntryAnchor); + if ($dir == 'RTL') { + if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) { + $x = 0; + } else { + $x = $x - ($pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000); + } + } + $html .= " Entry X: " . $x . " Y: " . $y . "; "; + } + if ($ExitAnchor != 0) { + $ExitAnchor += $subtable_offset; + list($x, $y) = $this->_getAnchorTable($ExitAnchor); + if ($dir == 'LTR') { + if (round($pdfWidth) == round($x * 1000 / $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'])) { + $x = 0; + } else { + $x = $x - ($pdfWidth * $this->mpdf->fonts[$this->fontkey]['desc']['unitsPerEm'] / 1000); + } + } + $html .= " Exit X: " . $x . " Y: " . $y . "; "; + } + + $html .= '</span></div>'; + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 4: MarkToBase attachment Attach a combining mark to a base glyph + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 4) { + $html .= '<div class="lookuptype">LookupType 4: MarkToBase attachment </div>'; + $MarkCoverage = $subtable_offset + $this->read_ushort(); + $BaseCoverage = $subtable_offset + $this->read_ushort(); + + $this->seek($MarkCoverage); + $MarkGlyphs = $this->_getCoverage(); + + $this->seek($BaseCoverage); + $BaseGlyphs = $this->_getCoverage(); + + $firstMark = ''; + $html .= '<div class="glyphs">Marks: '; + for ($i = 0; $i < count($MarkGlyphs); $i++) { + if ($level == 2 && strpos($lcoverage, $MarkGlyphs[$i]) === false) { + continue; + } else { + if (!$firstMark) { + $firstMark = $MarkGlyphs[$i]; + } + } + $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' '; + } + $html .= '</div>'; + if (!$firstMark) { + return; + } + + $html .= '<div class="glyphs">Bases: '; + for ($j = 0; $j < count($BaseGlyphs); $j++) { + $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . ' '; + } + $html .= '</div>'; + + // Example + $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): '; + for ($j = 0; $j < min(count($BaseGlyphs), 20); $j++) { + $html .= ' ' . $this->formatEntity($BaseGlyphs[$j]) . $this->formatEntity($firstMark, true) . '   '; + } + $html .= '</div>'; + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 5: MarkToLigature attachment Attach a combining mark to a ligature + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 5) { + $html .= '<div class="lookuptype">LookupType 5: MarkToLigature attachment </div>'; + $MarkCoverage = $subtable_offset + $this->read_ushort(); + //$MarkCoverage is already set in $lcoverage 00065|00073 etc + $LigatureCoverage = $subtable_offset + $this->read_ushort(); + $ClassCount = $this->read_ushort(); // Number of classes defined for marks = Number of mark glyphs in the MarkCoverage table + $MarkArray = $subtable_offset + $this->read_ushort(); // Offset to MarkArray table + $LigatureArray = $subtable_offset + $this->read_ushort(); // Offset to LigatureArray table + + $this->seek($MarkCoverage); + $MarkGlyphs = $this->_getCoverage(); + $this->seek($LigatureCoverage); + $LigatureGlyphs = $this->_getCoverage(); + + $firstMark = ''; + $html .= '<div class="glyphs">Marks: <span class="unchanged">'; + $MarkRecord = []; + for ($i = 0; $i < count($MarkGlyphs); $i++) { + if ($level == 2 && strpos($lcoverage, $MarkGlyphs[$i]) === false) { + continue; + } else { + if (!$firstMark) { + $firstMark = $MarkGlyphs[$i]; + } + } + // Get the relevant MarkRecord + $MarkRecord[$i] = $this->_getMarkRecord($MarkArray, $i); + //Mark Class is = $MarkRecord[$i]['Class'] + $html .= ' ' . $this->formatEntity($MarkGlyphs[$i]) . ' '; + } + $html .= '</span></div>'; + if (!$firstMark) { + return; + } + + $this->seek($LigatureArray); + $LigatureCount = $this->read_ushort(); + $LigatureAttach = []; + $html .= '<div class="glyphs">Ligatures: <span class="unchanged">'; + for ($j = 0; $j < count($LigatureGlyphs); $j++) { + // Get the relevant LigatureRecord + $LigatureAttach[$j] = $LigatureArray + $this->read_ushort(); + $html .= ' ' . $this->formatEntity($LigatureGlyphs[$j]) . ' '; + } + $html .= '</span></div>'; + + /* + for ($i=0;$i<count($MarkGlyphs);$i++) { + $html .= '<div class="glyphs">'; + $html .= '<span class="unchanged">'.$this->formatEntity($MarkGlyphs[$i]).'</span>'; + + for ($j=0;$j<count($LigatureGlyphs);$j++) { + $this->seek($LigatureAttach[$j]); + $ComponentCount = $this->read_ushort(); + $html .= '<span class="unchanged">'.$this->formatEntity($LigatureGlyphs[$j]).'</span>'; + $offsets = array(); + for ($comp=0;$comp<$ComponentCount;$comp++) { + // ComponentRecords + for ($class=0;$class<$ClassCount;$class++) { + $offset = $this->read_ushort(); + if ($offset!= 0 && $class == $MarkRecord[$i]['Class']) { + + $html .= ' ['.$comp.'] '; + + } + } + } + } + $html .= '</span></div>'; + } + */ + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 6: MarkToMark attachment Attach a combining mark to another mark + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 6) { + $html .= '<div class="lookuptype">LookupType 6: MarkToMark attachment </div>'; + $Mark1Coverage = $subtable_offset + $this->read_ushort(); // Combining Mark + //$Mark1Coverage is already set in $LuCoverage 0065|0073 etc + $Mark2Coverage = $subtable_offset + $this->read_ushort(); // Base Mark + $ClassCount = $this->read_ushort(); // Number of classes defined for marks = No. of Combining mark1 glyphs in the MarkCoverage table + $this->seek($Mark1Coverage); + $Mark1Glyphs = $this->_getCoverage(); + $this->seek($Mark2Coverage); + $Mark2Glyphs = $this->_getCoverage(); + + $firstMark = ''; + $html .= '<div class="glyphs">Marks: <span class="unchanged">'; + for ($i = 0; $i < count($Mark1Glyphs); $i++) { + if ($level == 2 && strpos($lcoverage, $Mark1Glyphs[$i]) === false) { + continue; + } else { + if (!$firstMark) { + $firstMark = $Mark1Glyphs[$i]; + } + } + $html .= ' ' . $this->formatEntity($Mark1Glyphs[$i]) . ' '; + } + $html .= '</span></div>'; + + if ($firstMark) { + $html .= '<div class="glyphs">Bases: <span class="unchanged">'; + for ($j = 0; $j < count($Mark2Glyphs); $j++) { + $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . ' '; + } + $html .= '</span></div>'; + + // Example + $html .= '<div class="glyphs" style="font-feature-settings:\'' . $tag . '\' 1;">Example(s): <span class="changed">'; + for ($j = 0; $j < min(count($Mark2Glyphs), 20); $j++) { + $html .= ' ' . $this->formatEntity($Mark2Glyphs[$j]) . $this->formatEntity($firstMark, true) . '   '; + } + $html .= '</span></div>'; + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 7: Context positioning Position one or more glyphs in context + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 7) { + $html .= '<div class="lookuptype">LookupType 7: Context positioning [Format ' . $PosFormat . ']</div>'; + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED."); + } //=========== + // Format 2: + //=========== + else { + if ($PosFormat == 2) { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED."); + } //=========== + // Format 3: + //=========== + else { + if ($PosFormat == 3) { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not YET TESTED."); + } else { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported."); + } + } + } + } //////////////////////////////////////////////////////////////////////////////// + // LookupType 8: Chained Context positioning Position one or more glyphs in chained context + //////////////////////////////////////////////////////////////////////////////// + else { + if ($Lookup[$luli]['Type'] == 8) { + $html .= '<div class="lookuptype">LookupType 8: Chained Context positioning [Format ' . $PosFormat . ']</div>'; + //=========== + // Format 1: + //=========== + if ($PosFormat == 1) { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET."); + } //=========== + // Format 2: + //=========== + else { + if ($PosFormat == 2) { + $html .= '<div>GPOS Lookup Type 8: Format 2 not yet supported in OTL dump</div>'; + continue; + /* NB When developing - cf. GSUB 6.2 */ + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET."); + } //=========== + // Format 3: + //=========== + else { + if ($PosFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + $CoverageBacktrackOffset = []; + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $InputGlyphCount = $this->read_ushort(); + $CoverageInputOffset = []; + for ($b = 0; $b < $InputGlyphCount; $b++) { + $CoverageInputOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $LookaheadGlyphCount = $this->read_ushort(); + $CoverageLookaheadOffset = []; + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort(); // in glyph sequence order + } + $PosCount = $this->read_ushort(); + + $PosLookupRecord = []; + for ($p = 0; $p < $PosCount; $p++) { + // PosLookupRecord + $PosLookupRecord[$p]['SequenceIndex'] = $this->read_ushort(); + $PosLookupRecord[$p]['LookupListIndex'] = $this->read_ushort(); + } + + $backtrackGlyphs = []; + for ($b = 0; $b < $BacktrackGlyphCount; $b++) { + $this->seek($CoverageBacktrackOffset[$b]); + $backtrackGlyphs[$b] = implode('|', $this->_getCoverage()); + } + $inputGlyphs = []; + for ($b = 0; $b < $InputGlyphCount; $b++) { + $this->seek($CoverageInputOffset[$b]); + $inputGlyphs[$b] = implode('|', $this->_getCoverage()); + } + $lookaheadGlyphs = []; + for ($b = 0; $b < $LookaheadGlyphCount; $b++) { + $this->seek($CoverageLookaheadOffset[$b]); + $lookaheadGlyphs[$b] = implode('|', $this->_getCoverage()); + } + + $exampleB = []; + $exampleI = []; + $exampleL = []; + $html .= '<div class="context">CONTEXT: '; + for ($ff = count($backtrackGlyphs) - 1; $ff >= 0; $ff--) { + $html .= '<div>Backtrack #' . $ff . ': <span class="unicode">' . $this->formatUniStr($backtrackGlyphs[$ff]) . '</span></div>'; + $exampleB[] = $this->formatEntityFirst($backtrackGlyphs[$ff]); + } + for ($ff = 0; $ff < count($inputGlyphs); $ff++) { + $html .= '<div>Input #' . $ff . ': <span class="unchanged"> ' . $this->formatEntityStr($inputGlyphs[$ff]) . ' </span></div>'; + $exampleI[] = $this->formatEntityFirst($inputGlyphs[$ff]); + } + for ($ff = 0; $ff < count($lookaheadGlyphs); $ff++) { + $html .= '<div>Lookahead #' . $ff . ': <span class="unicode">' . $this->formatUniStr($lookaheadGlyphs[$ff]) . '</span></div>'; + $exampleL[] = $this->formatEntityFirst($lookaheadGlyphs[$ff]); + } + $html .= '</div>'; + + for ($p = 0; $p < $PosCount; $p++) { + $lup = $PosLookupRecord[$p]['LookupListIndex']; + $seqIndex = $PosLookupRecord[$p]['SequenceIndex']; + + // GENERATE exampleB[n] exampleI[<seqIndex] .... exampleI[>seqIndex] exampleL[n] + $exB = ''; + $exL = ''; + if (count($exampleB)) { + $exB .= '<span class="backtrack">' . implode('‍', $exampleB) . '</span>'; + } + + if ($seqIndex > 0) { + $exB .= '<span class="inputother">'; + for ($ip = 0; $ip < $seqIndex; $ip++) { + $exB .= $exampleI[$ip] . '‍'; + } + $exB .= '</span>'; + } + + if (count($inputGlyphs) > ($seqIndex + 1)) { + $exL .= '<span class="inputother">'; + for ($ip = $seqIndex + 1; $ip < count($inputGlyphs); $ip++) { + $exL .= '‍' . $exampleI[$ip]; + } + $exL .= '</span>'; + } + + if (count($exampleL)) { + $exL .= '<span class="lookahead">' . implode('‍', $exampleL) . '</span>'; + } + + $html .= '<div class="sequenceIndex">Substitution Position: ' . $seqIndex . '</div>'; + + $lul2 = [$lup => $tag]; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // Pass $inputGlyphs[$seqIndex] e.g. 00636|00645|00656 + // to level 2 and only apply if first Replace glyph is in this list + $html .= $this->_getGPOSarray($Lookup, $lul2, $scripttag, 2, $inputGlyphs[$seqIndex], $exB, $exL); + } + } + } + } + } + } + } + } + } + } + } + } + } + $html .= '</div>'; + } + if ($level == 1) { + $this->mpdf->WriteHTML($html); + } else { + return $html; + } +//print_r($Lookup); exit; + } + + //===================================================================================== + //===================================================================================== + // GPOS FUNCTIONS + //===================================================================================== + + function count_bits($n) + { + for ($c = 0; $n; $c++) { + $n &= $n - 1; // clear the least significant bit set + } + + return $c; + } + + function _getValueRecord($ValueFormat) + { + // Common ValueRecord for GPOS + // Only returns 3 possible: $vra['XPlacement'] $vra['YPlacement'] $vra['XAdvance'] + $vra = []; + // Horizontal adjustment for placement-in design units + if (($ValueFormat & 0x0001) == 0x0001) { + $vra['XPlacement'] = $this->read_short(); + } + // Vertical adjustment for placement-in design units + if (($ValueFormat & 0x0002) == 0x0002) { + $vra['YPlacement'] = $this->read_short(); + } + // Horizontal adjustment for advance-in design units (only used for horizontal writing) + if (($ValueFormat & 0x0004) == 0x0004) { + $vra['XAdvance'] = $this->read_short(); + } + // Vertical adjustment for advance-in design units (only used for vertical writing) + if (($ValueFormat & 0x0008) == 0x0008) { + $this->read_short(); + } + // Offset to Device table for horizontal placement-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0010) == 0x0010) { + $this->read_ushort(); + } + // Offset to Device table for vertical placement-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0020) == 0x0020) { + $this->read_ushort(); + } + // Offset to Device table for horizontal advance-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0040) == 0x0040) { + $this->read_ushort(); + } + // Offset to Device table for vertical advance-measured from beginning of PosTable (may be NULL) + if (($ValueFormat & 0x0080) == 0x0080) { + $this->read_ushort(); + } + + return $vra; + } + + function _getAnchorTable($offset = 0) + { + if ($offset) { + $this->seek($offset); + } + $AnchorFormat = $this->read_ushort(); + $XCoordinate = $this->read_short(); + $YCoordinate = $this->read_short(); + + // Format 2 specifies additional link to contour point; Format 3 additional Device table + return [$XCoordinate, $YCoordinate]; + } + + function _getMarkRecord($offset, $MarkPos) + { + $this->seek($offset); + $MarkCount = $this->read_ushort(); + $this->skip($MarkPos * 4); + $Class = $this->read_ushort(); + $MarkAnchor = $offset + $this->read_ushort(); // = Offset to anchor table + list($x, $y) = $this->_getAnchorTable($MarkAnchor); + $MarkRecord = ['Class' => $Class, 'AnchorX' => $x, 'AnchorY' => $y]; + + return $MarkRecord; + } + + ////////////////////////////////////////////////////////////////////////////////// + // Recursively get composite glyph data + function getGlyphData($originalGlyphIdx, &$maxdepth, &$depth, &$points, &$contours) + { + $depth++; + $maxdepth = max($maxdepth, $depth); + if (count($this->glyphdata[$originalGlyphIdx]['compGlyphs'])) { + foreach ($this->glyphdata[$originalGlyphIdx]['compGlyphs'] as $glyphIdx) { + $this->getGlyphData($glyphIdx, $maxdepth, $depth, $points, $contours); + } + } else { + if (($this->glyphdata[$originalGlyphIdx]['nContours'] > 0) && $depth > 0) { // simple + $contours += $this->glyphdata[$originalGlyphIdx]['nContours']; + $points += $this->glyphdata[$originalGlyphIdx]['nPoints']; + } + } + $depth--; + } + + ////////////////////////////////////////////////////////////////////////////////// + // Recursively get composite glyphs + function getGlyphs($originalGlyphIdx, &$start, &$glyphSet, &$subsetglyphs) + { + $glyphPos = $this->glyphPos[$originalGlyphIdx]; + $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos; + if (!$glyphLen) { + return; + } + $this->seek($start + $glyphPos); + $numberOfContours = $this->read_short(); + if ($numberOfContours < 0) { + $this->skip(8); + $flags = GlyphOperator::MORE; + while ($flags & GlyphOperator::MORE) { + $flags = $this->read_ushort(); + } + $glyphIdx = $this->read_ushort(); + if (!isset($glyphSet[$glyphIdx])) { + $glyphSet[$glyphIdx] = count($subsetglyphs); // old glyphID to new glyphID + $subsetglyphs[$glyphIdx] = true; + } + $savepos = ftell($this->fh); + $this->getGlyphs($glyphIdx, $start, $glyphSet, $subsetglyphs); + $this->seek($savepos); + if ($flags & GlyphOperator::WORDS) { + $this->skip(4); + } else { + $this->skip(2); + } + if ($flags & GlyphOperator::SCALE) { + $this->skip(2); + } else { + if ($flags & GlyphOperator::XYSCALE) { + $this->skip(4); + } else { + if ($flags & GlyphOperator::TWOBYTWO) { + $this->skip(8); + } + } + } + } + } + + + ////////////////////////////////////////////////////////////////////////////////// + + function getHMTX($numberOfHMetrics, $numGlyphs, &$glyphToChar, $scale) + { + $start = $this->seek_table("hmtx"); + $aw = 0; + $this->charWidths = str_pad('', 256 * 256 * 2, "\x00"); + if ($this->maxUniChar > 65536) { + $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00"); + } // Plane 1 SMP + if ($this->maxUniChar > 131072) { + $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00"); + } // Plane 2 SMP + $nCharWidths = 0; + if (($numberOfHMetrics * 4) < $this->maxStrLenRead) { + $data = $this->get_chunk($start, ($numberOfHMetrics * 4)); + $arr = unpack("n*", $data); + } else { + $this->seek($start); + } + for ($glyph = 0; $glyph < $numberOfHMetrics; $glyph++) { + if (($numberOfHMetrics * 4) < $this->maxStrLenRead) { + $aw = $arr[($glyph * 2) + 1]; + } else { + $aw = $this->read_ushort(); + $lsb = $this->read_ushort(); + } + if (isset($glyphToChar[$glyph]) || $glyph == 0) { + if ($aw >= (1 << 15)) { + $aw = 0; + } // 1.03 Some (arabic) fonts have -ve values for width + // although should be unsigned value - comes out as e.g. 65108 (intended -50) + if ($glyph == 0) { + $this->defaultWidth = $scale * $aw; + continue; + } + foreach ($glyphToChar[$glyph] as $char) { + //$this->charWidths[$char] = intval(round($scale*$aw)); + if ($char != 0 && $char != 65535) { + $w = intval(round($scale * $aw)); + if ($w == 0) { + $w = 65535; + } + if ($char < 196608) { + $this->charWidths[$char * 2] = chr($w >> 8); + $this->charWidths[$char * 2 + 1] = chr($w & 0xFF); + $nCharWidths++; + } + } + } + } + } + $data = $this->get_chunk(($start + $numberOfHMetrics * 4), ($numGlyphs * 2)); + $arr = unpack("n*", $data); + $diff = $numGlyphs - $numberOfHMetrics; + $w = intval(round($scale * $aw)); + if ($w == 0) { + $w = 65535; + } + for ($pos = 0; $pos < $diff; $pos++) { + $glyph = $pos + $numberOfHMetrics; + if (isset($glyphToChar[$glyph])) { + foreach ($glyphToChar[$glyph] as $char) { + if ($char != 0 && $char != 65535) { + if ($char < 196608) { + $this->charWidths[$char * 2] = chr($w >> 8); + $this->charWidths[$char * 2 + 1] = chr($w & 0xFF); + $nCharWidths++; + } + } + } + } + } + // NB 65535 is a set width of 0 + // First bytes define number of chars in font + $this->charWidths[0] = chr($nCharWidths >> 8); + $this->charWidths[1] = chr($nCharWidths & 0xFF); + } + + function getHMetric($numberOfHMetrics, $gid) + { + $start = $this->seek_table("hmtx"); + if ($gid < $numberOfHMetrics) { + $this->seek($start + ($gid * 4)); + $hm = fread($this->fh, 4); + } else { + $this->seek($start + (($numberOfHMetrics - 1) * 4)); + $hm = fread($this->fh, 2); + $this->seek($start + ($numberOfHMetrics * 2) + ($gid * 2)); + $hm .= fread($this->fh, 2); + } + + return $hm; + } + + function getLOCA($indexToLocFormat, $numGlyphs) + { + $start = $this->seek_table('loca'); + $this->glyphPos = []; + if ($indexToLocFormat == 0) { + $data = $this->get_chunk($start, ($numGlyphs * 2) + 2); + $arr = unpack("n*", $data); + for ($n = 0; $n <= $numGlyphs; $n++) { + $this->glyphPos[] = ($arr[$n + 1] * 2); + } + } else { + if ($indexToLocFormat == 1) { + $data = $this->get_chunk($start, ($numGlyphs * 4) + 4); + $arr = unpack("N*", $data); + for ($n = 0; $n <= $numGlyphs; $n++) { + $this->glyphPos[] = ($arr[$n + 1]); + } + } else { + throw new \Mpdf\Exception\FontException('Unknown location table format ' . $indexToLocFormat); + } + } + } + + // CMAP Format 4 + function getCMAP4($unicode_cmap_offset, &$glyphToChar, &$charToGlyph) + { + $this->maxUniChar = 0; + $this->seek($unicode_cmap_offset + 2); + $length = $this->read_ushort(); + $limit = $unicode_cmap_offset + $length; + $this->skip(2); + + $segCount = $this->read_ushort() / 2; + $this->skip(6); + $endCount = []; + for ($i = 0; $i < $segCount; $i++) { + $endCount[] = $this->read_ushort(); + } + $this->skip(2); + $startCount = []; + for ($i = 0; $i < $segCount; $i++) { + $startCount[] = $this->read_ushort(); + } + $idDelta = []; + for ($i = 0; $i < $segCount; $i++) { + $idDelta[] = $this->read_short(); + } // ???? was unsigned short + $idRangeOffset_start = $this->_pos; + $idRangeOffset = []; + for ($i = 0; $i < $segCount; $i++) { + $idRangeOffset[] = $this->read_ushort(); + } + + for ($n = 0; $n < $segCount; $n++) { + $endpoint = ($endCount[$n] + 1); + for ($unichar = $startCount[$n]; $unichar < $endpoint; $unichar++) { + if ($idRangeOffset[$n] == 0) { + $glyph = ($unichar + $idDelta[$n]) & 0xFFFF; + } else { + $offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n]; + $offset = $idRangeOffset_start + 2 * $n + $offset; + if ($offset >= $limit) { + $glyph = 0; + } else { + $glyph = $this->get_ushort($offset); + if ($glyph != 0) { + $glyph = ($glyph + $idDelta[$n]) & 0xFFFF; + } + } + } + $charToGlyph[$unichar] = $glyph; + if ($unichar < 196608) { + $this->maxUniChar = max($unichar, $this->maxUniChar); + } + $glyphToChar[$glyph][] = $unichar; + } + } + } + + function formatUni($char) + { + $x = preg_replace('/^[0]*/', '', $char); + $x = str_pad($x, 4, '0', STR_PAD_LEFT); + $d = hexdec($x); + if (($d > 57343 && $d < 63744) || ($d > 122879 && $d < 126977)) { + $id = 'M'; + } // E000 - F8FF, 1E000-1F000 + else { + $id = 'U'; + } + + return $id . '+' . $x; + } + + function formatEntity($char, $allowjoining = false) + { + $char = preg_replace('/^[0]/', '', $char); + $x = '&#x' . $char . ';'; + if (strpos($this->GlyphClassMarks, $char) !== false) { + if (!$allowjoining) { + $x = '◌' . $x; + } + } + + return $x; + } + + function formatUniArr($arr) + { + $s = []; + foreach ($arr as $c) { + $x = preg_replace('/^[0]*/', '', $c); + $d = hexdec($x); + if (($d > 57343 && $d < 63744) || ($d > 122879 && $d < 126977)) { + $id = 'M'; + } // E000 - F8FF, 1E000-1F000 + else { + $id = 'U'; + } + $s[] = $id . '+' . str_pad($x, 4, '0', STR_PAD_LEFT); + } + + return implode(', ', $s); + } + + function formatEntityArr($arr) + { + $s = []; + foreach ($arr as $c) { + $c = preg_replace('/^[0]/', '', $c); + $x = '&#x' . $c . ';'; + if (strpos($this->GlyphClassMarks, $c) !== false) { + $x = '◌' . $x; + } + $s[] = $x; + } + + return implode(' ', $s); // ZWNJ? ‍ + } + + function formatClassArr($arr) + { + $s = []; + foreach ($arr as $c) { + $x = preg_replace('/^[0]*/', '', $c); + $d = hexdec($x); + if (($d > 57343 && $d < 63744) || ($d > 122879 && $d < 126977)) { + $id = 'M'; + } // E000 - F8FF, 1E000-1F000 + else { + $id = 'U'; + } + $s[] = $id . '+' . str_pad($x, 4, '0', STR_PAD_LEFT); + } + + return implode(', ', $s); + } + + function formatUniStr($str) + { + $s = []; + $arr = explode('|', $str); + foreach ($arr as $c) { + $x = preg_replace('/^[0]*/', '', $c); + $d = hexdec($x); + if (($d > 57343 && $d < 63744) || ($d > 122879 && $d < 126977)) { + $id = 'M'; + } // E000 - F8FF, 1E000-1F000 + else { + $id = 'U'; + } + $s[] = $id . '+' . str_pad($x, 4, '0', STR_PAD_LEFT); + } + + return implode(', ', $s); + } + + function formatEntityStr($str) + { + $s = []; + $arr = explode('|', $str); + foreach ($arr as $c) { + $c = preg_replace('/^[0]/', '', $c); + $x = '&#x' . $c . ';'; + if (strpos($this->GlyphClassMarks, $c) !== false) { + $x = '◌' . $x; + } + $s[] = $x; + } + + return implode(' ', $s); // ZWNJ? ‍ + } + + function formatEntityFirst($str) + { + $arr = explode('|', $str); + $char = preg_replace('/^[0]/', '', $arr[0]); + $x = '&#x' . $char . ';'; + if (strpos($this->GlyphClassMarks, $char) !== false) { + $x = '◌' . $x; + } + + return $x; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Output/Destination.php b/src/vendor/mpdf/mpdf/src/Output/Destination.php new file mode 100644 index 000000000..25b46d6a4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Output/Destination.php @@ -0,0 +1,15 @@ +<?php + +namespace Mpdf\Output; + +class Destination +{ + + const FILE = 'F'; + + const DOWNLOAD = 'D'; + + const STRING_RETURN = 'S'; + + const INLINE = 'I'; +} diff --git a/src/vendor/mpdf/mpdf/src/PageBox.php b/src/vendor/mpdf/mpdf/src/PageBox.php new file mode 100644 index 000000000..773c23e69 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/PageBox.php @@ -0,0 +1,56 @@ +<?php + +namespace Mpdf; + +class PageBox implements \ArrayAccess +{ + + private $container = []; + + public function __construct() + { + $this->container = [ + 'current' => null, + 'outer_width_LR' => null, + 'outer_width_TB' => null, + 'using' => null, + ]; + } + + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + if (!$this->offsetExists($offset)) { + throw new \Mpdf\MpdfException('Invalid key to set for PageBox'); + } + + $this->container[$offset] = $value; + } + + #[\ReturnTypeWillChange] + public function offsetExists($offset) + { + return array_key_exists($offset, $this->container); + } + + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + if (!$this->offsetExists($offset)) { + throw new \Mpdf\MpdfException('Invalid key to set for PageBox'); + } + + $this->container[$offset] = null; + } + + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + if (!$this->offsetExists($offset)) { + throw new \Mpdf\MpdfException('Invalid key to set for PageBox'); + } + + return $this->container[$offset]; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/PageFormat.php b/src/vendor/mpdf/mpdf/src/PageFormat.php new file mode 100644 index 000000000..57a534e07 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/PageFormat.php @@ -0,0 +1,83 @@ +<?php + +namespace Mpdf; + +class PageFormat +{ + + /** + * This method returns an array of width and height of given named format. + * + * Returned values are milimeters multiplied by scale factor of 72 / 25.4 + * + * @param string $name + * @return float[] Width and height of given format + */ + public static function getSizeFromName($name) + { + $format = strtoupper($name); + $formats = [ + '4A0' => [4767.87, 6740.79], + '2A0' => [3370.39, 4767.87], + 'A0' => [2383.94, 3370.39], + 'A1' => [1683.78, 2383.94], + 'A2' => [1190.55, 1683.78], + 'A3' => [841.89, 1190.55], + 'A4' => [595.28, 841.89], + 'A5' => [419.53, 595.28], + 'A6' => [297.64, 419.53], + 'A7' => [209.76, 297.64], + 'A8' => [147.40, 209.76], + 'A9' => [104.88, 147.40], + 'A10' => [73.70, 104.88], + 'B0' => [2834.65, 4008.19], + 'B1' => [2004.09, 2834.65], + 'B2' => [1417.32, 2004.09], + 'B3' => [1000.63, 1417.32], + 'B4' => [708.66, 1000.63], + 'B5' => [498.90, 708.66], + 'B6' => [354.33, 498.90], + 'B7' => [249.45, 354.33], + 'B8' => [175.75, 249.45], + 'B9' => [124.72, 175.75], + 'B10' => [87.87, 124.72], + 'C0' => [2599.37, 3676.54], + 'C1' => [1836.85, 2599.37], + 'C2' => [1298.27, 1836.85], + 'C3' => [918.43, 1298.27], + 'C4' => [649.13, 918.43], + 'C5' => [459.21, 649.13], + 'C6' => [323.15, 459.21], + 'C7' => [229.61, 323.15], + 'C8' => [161.57, 229.61], + 'C9' => [113.39, 161.57], + 'C10' => [79.37, 113.39], + 'RA0' => [2437.80, 3458.27], + 'RA1' => [1729.13, 2437.80], + 'RA2' => [1218.90, 1729.13], + 'RA3' => [864.57, 1218.90], + 'RA4' => [609.45, 864.57], + 'SRA0' => [2551.18, 3628.35], + 'SRA1' => [1814.17, 2551.18], + 'SRA2' => [1275.59, 1814.17], + 'SRA3' => [907.09, 1275.59], + 'SRA4' => [637.80, 907.09], + 'LETTER' => [612.00, 792.00], + 'LEGAL' => [612.00, 1008.00], + 'LEDGER' => [1224.00, 792.00], + 'TABLOID' => [792.00, 1224.00], + 'EXECUTIVE' => [521.86, 756.00], + 'FOLIO' => [612.00, 936.00], + 'B' => [362.83, 561.26], // 'B' format paperback size 128x198mm + 'A' => [314.65, 504.57], // 'A' format paperback size 111x178mm + 'DEMY' => [382.68, 612.28], // 'Demy' format paperback size 135x216mm + 'ROYAL' => [433.70, 663.30], // 'Royal' format paperback size 153x234mm + ]; + + if (!isset($formats[$format])) { + throw new \Mpdf\MpdfException(sprintf('Unknown page format %s', $format)); + } + + return $formats[$format]; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Pdf/Protection.php b/src/vendor/mpdf/mpdf/src/Pdf/Protection.php new file mode 100644 index 000000000..d39c77dfb --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Pdf/Protection.php @@ -0,0 +1,360 @@ +<?php + +namespace Mpdf\Pdf; + +use Mpdf\Pdf\Protection\UniqidGenerator; + +class Protection +{ + + /** + * @var string + */ + private $lastRc4Key; + + /** + * @var string + */ + private $lastRc4KeyC; + + /** + * @var bool + */ + private $useRC128Encryption; + + /** + * @var string + */ + private $encryptionKey; + + /** + * @var string + */ + private $padding; + + /** + * @var string + */ + private $uniqid; + + /** + * @var string + */ + private $oValue; + + /** + * @var string + */ + private $uValue; + + /** + * @var string + */ + private $pValue; + + /** + * @var int[] Array of permission => byte representation + */ + private $options; + + /** + * @var \Mpdf\Pdf\Protection\UniqidGenerator + */ + private $uniqidGenerator; + + public function __construct(UniqidGenerator $uniqidGenerator) + { + if (!function_exists('random_int') || !function_exists('random_bytes')) { + throw new \Mpdf\MpdfException( + 'Unable to set PDF file protection, CSPRNG Functions are not available. ' + . 'Use paragonie/random_compat polyfill or upgrade to PHP 7.' + ); + } + + $this->uniqidGenerator = $uniqidGenerator; + + $this->lastRc4Key = ''; + + $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08" . + "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; + + $this->useRC128Encryption = false; + + $this->options = [ + 'print' => 4, // bit 3 + 'modify' => 8, // bit 4 + 'copy' => 16, // bit 5 + 'annot-forms' => 32, // bit 6 + 'fill-forms' => 256, // bit 9 + 'extract' => 512, // bit 10 + 'assemble' => 1024, // bit 11 + 'print-highres' => 2048 // bit 12 + ]; + } + + /** + * @param array $permissions + * @param string $user_pass + * @param string $owner_pass + * @param int $length + * + * @return bool + */ + public function setProtection($permissions = [], $user_pass = '', $owner_pass = null, $length = 40) + { + if (is_string($permissions) && strlen($permissions) > 0) { + $permissions = [$permissions]; + } elseif (!is_array($permissions)) { + return false; + } + + $protection = $this->getProtectionBitsFromOptions($permissions); + + if ($length === 128) { + $this->useRC128Encryption = true; + } elseif ($length !== 40) { + throw new \Mpdf\MpdfException('PDF protection only allows lenghts of 40 or 128'); + } + + if ($owner_pass === null) { + $owner_pass = bin2hex(random_bytes(23)); + } + + $this->generateEncryptionKey($user_pass, $owner_pass, $protection); + + return true; + } + + /** + * Compute key depending on object number where the encrypted data is stored + * + * @param int $n + * + * @return string + */ + public function objectKey($n) + { + if ($this->useRC128Encryption) { + $len = 16; + } else { + $len = 10; + } + + return substr($this->md5toBinary($this->encryptionKey . pack('VXxx', $n)), 0, $len); + } + + /** + * RC4 is the standard encryption algorithm used in PDF format + * + * @param string $key + * @param string $text + * + * @return string + */ + public function rc4($key, $text) + { + if ($this->lastRc4Key != $key) { + $k = str_repeat($key, round(256 / strlen($key)) + 1); + $rc4 = range(0, 255); + $j = 0; + for ($i = 0; $i < 256; $i++) { + $t = $rc4[$i]; + $j = ($j + $t + ord($k[$i])) % 256; + $rc4[$i] = $rc4[$j]; + $rc4[$j] = $t; + } + $this->lastRc4Key = $key; + $this->lastRc4KeyC = $rc4; + } else { + $rc4 = $this->lastRc4KeyC; + } + + $len = strlen($text); + $a = 0; + $b = 0; + $out = ''; + for ($i = 0; $i < $len; $i++) { + $a = ($a + 1) % 256; + $t = $rc4[$a]; + $b = ($b + $t) % 256; + $rc4[$a] = $rc4[$b]; + $rc4[$b] = $t; + $k = $rc4[($rc4[$a] + $rc4[$b]) % 256]; + $out .= chr(ord($text[$i]) ^ $k); + } + + return $out; + } + + /** + * @return mixed + */ + public function getUseRC128Encryption() + { + return $this->useRC128Encryption; + } + + /** + * @return mixed + */ + public function getUniqid() + { + return $this->uniqid; + } + + /** + * @return mixed + */ + public function getOValue() + { + return $this->oValue; + } + + /** + * @return mixed + */ + public function getUValue() + { + return $this->uValue; + } + + /** + * @return mixed + */ + public function getPValue() + { + return $this->pValue; + } + + private function getProtectionBitsFromOptions($permissions) + { + // bit 31 = 1073741824 + // bit 32 = 2147483648 + // bits 13-31 = 2147479552 + // bits 13-32 = 4294963200 + 192 = 4294963392 + + $protection = 4294963392; // bits 7, 8, 13-32 + + foreach ($permissions as $permission) { + if (!isset($this->options[$permission])) { + throw new \Mpdf\MpdfException(sprintf('Invalid permission type "%s"', $permission)); + } + if ($this->options[$permission] > 32) { + $this->useRC128Encryption = true; + } + if (isset($this->options[$permission])) { + $protection += $this->options[$permission]; + } + } + + return $protection; + } + + private function oValue($user_pass, $owner_pass) + { + $tmp = $this->md5toBinary($owner_pass); + if ($this->useRC128Encryption) { + for ($i = 0; $i < 50; ++$i) { + $tmp = $this->md5toBinary($tmp); + } + } + if ($this->useRC128Encryption) { + $keybytelen = (128 / 8); + } else { + $keybytelen = (40 / 8); + } + $owner_rc4_key = substr($tmp, 0, $keybytelen); + $enc = $this->rc4($owner_rc4_key, $user_pass); + if ($this->useRC128Encryption) { + $len = strlen($owner_rc4_key); + for ($i = 1; $i <= 19; ++$i) { + $key = ''; + for ($j = 0; $j < $len; ++$j) { + $key .= chr(ord($owner_rc4_key[$j]) ^ $i); + } + $enc = $this->rc4($key, $enc); + } + } + + return $enc; + } + + private function uValue() + { + if ($this->useRC128Encryption) { + $tmp = $this->md5toBinary($this->padding . $this->hexToString($this->uniqid)); + $enc = $this->rc4($this->encryptionKey, $tmp); + $len = strlen($tmp); + for ($i = 1; $i <= 19; ++$i) { + $key = ''; + for ($j = 0; $j < $len; ++$j) { + $key .= chr(ord($this->encryptionKey[$j]) ^ $i); + } + $enc = $this->rc4($key, $enc); + } + $enc .= str_repeat("\x00", 16); + + return substr($enc, 0, 32); + } else { + return $this->rc4($this->encryptionKey, $this->padding); + } + } + + private function generateEncryptionKey($user_pass, $owner_pass, $protection) + { + // Pad passwords + $user_pass = substr($user_pass . $this->padding, 0, 32); + $owner_pass = substr($owner_pass . $this->padding, 0, 32); + + $this->oValue = $this->oValue($user_pass, $owner_pass); + + $this->uniqid = $this->uniqidGenerator->generate(); + + // Compute encyption key + if ($this->useRC128Encryption) { + $keybytelen = (128 / 8); + } else { + $keybytelen = (40 / 8); + } + + $prot = sprintf('%032b', $protection); + + $perms = chr(bindec(substr($prot, 24, 8))); + $perms .= chr(bindec(substr($prot, 16, 8))); + $perms .= chr(bindec(substr($prot, 8, 8))); + $perms .= chr(bindec(substr($prot, 0, 8))); + + $tmp = $this->md5toBinary($user_pass . $this->oValue . $perms . $this->hexToString($this->uniqid)); + + if ($this->useRC128Encryption) { + for ($i = 0; $i < 50; ++$i) { + $tmp = $this->md5toBinary(substr($tmp, 0, $keybytelen)); + } + } + + $this->encryptionKey = substr($tmp, 0, $keybytelen); + + $this->uValue = $this->uValue(); + $this->pValue = $protection; + } + + private function md5toBinary($string) + { + return pack('H*', md5($string)); + } + + private function hexToString($hs) + { + $s = ''; + $len = strlen($hs); + if (($len % 2) != 0) { + $hs .= '0'; + ++$len; + } + for ($i = 0; $i < $len; $i += 2) { + $s .= chr(hexdec($hs[$i] . $hs[($i + 1)])); + } + + return $s; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php b/src/vendor/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php new file mode 100644 index 000000000..54753d451 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php @@ -0,0 +1,32 @@ +<?php + +namespace Mpdf\Pdf\Protection; + +class UniqidGenerator +{ + + public function __construct() + { + if (!function_exists('random_int') || !function_exists('random_bytes')) { + throw new \Mpdf\MpdfException( + 'Unable to set PDF file protection, CSPRNG Functions are not available. ' + . 'Use paragonie/random_compat polyfill or upgrade to PHP 7.' + ); + } + } + + /** + * @return string + */ + public function generate() + { + $chars = 'ABCDEF1234567890'; + $id = ''; + + for ($i = 0; $i < 32; $i++) { + $id .= $chars[random_int(0, 15)]; + } + + return md5($id); + } +} diff --git a/src/vendor/mpdf/mpdf/src/ServiceFactory.php b/src/vendor/mpdf/mpdf/src/ServiceFactory.php new file mode 100644 index 000000000..79633e7e4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/ServiceFactory.php @@ -0,0 +1,234 @@ +<?php + +namespace Mpdf; + +use Mpdf\Color\ColorConverter; +use Mpdf\Color\ColorModeConverter; +use Mpdf\Color\ColorSpaceRestrictor; +use Mpdf\File\LocalContentLoader; +use Mpdf\Fonts\FontCache; +use Mpdf\Fonts\FontFileFinder; +use Mpdf\Http\CurlHttpClient; +use Mpdf\Http\SocketHttpClient; +use Mpdf\Image\ImageProcessor; +use Mpdf\Pdf\Protection; +use Mpdf\Pdf\Protection\UniqidGenerator; +use Mpdf\Writer\BaseWriter; +use Mpdf\Writer\BackgroundWriter; +use Mpdf\Writer\ColorWriter; +use Mpdf\Writer\BookmarkWriter; +use Mpdf\Writer\FontWriter; +use Mpdf\Writer\FormWriter; +use Mpdf\Writer\ImageWriter; +use Mpdf\Writer\JavaScriptWriter; +use Mpdf\Writer\MetadataWriter; +use Mpdf\Writer\OptionalContentWriter; +use Mpdf\Writer\PageWriter; +use Mpdf\Writer\ResourceWriter; +use Psr\Log\LoggerInterface; + +class ServiceFactory +{ + + /** + * @var \Mpdf\Container\ContainerInterface|null + */ + private $container; + + public function __construct($container = null) + { + $this->container = $container; + } + + public function getServices( + Mpdf $mpdf, + LoggerInterface $logger, + $config, + $languageToFont, + $scriptToLanguage, + $fontDescriptor, + $bmp, + $directWrite, + $wmf + ) { + $sizeConverter = new SizeConverter($mpdf->dpi, $mpdf->default_font_size, $mpdf, $logger); + + $colorModeConverter = new ColorModeConverter(); + $colorSpaceRestrictor = new ColorSpaceRestrictor( + $mpdf, + $colorModeConverter + ); + $colorConverter = new ColorConverter($mpdf, $colorModeConverter, $colorSpaceRestrictor); + + $tableOfContents = new TableOfContents($mpdf, $sizeConverter); + + $cacheBasePath = $config['tempDir'] . '/mpdf'; + + $cache = new Cache($cacheBasePath, $config['cacheCleanupInterval']); + $fontCache = new FontCache(new Cache($cacheBasePath . '/ttfontdata', $config['cacheCleanupInterval'])); + + $fontFileFinder = new FontFileFinder($config['fontDir']); + + if ($this->container && $this->container->has('httpClient')) { + $httpClient = $this->container->get('httpClient'); + } elseif (\function_exists('curl_init')) { + $httpClient = new CurlHttpClient($mpdf, $logger); + } else { + $httpClient = new SocketHttpClient($logger); + } + + $localContentLoader = $this->container && $this->container->has('localContentLoader') + ? $this->container->get('localContentLoader') + : new LocalContentLoader(); + + $assetFetcher = new AssetFetcher($mpdf, $localContentLoader, $httpClient, $logger); + + $cssManager = new CssManager($mpdf, $cache, $sizeConverter, $colorConverter, $assetFetcher); + + $otl = new Otl($mpdf, $fontCache); + + $protection = new Protection(new UniqidGenerator()); + + $writer = new BaseWriter($mpdf, $protection); + + $gradient = new Gradient($mpdf, $sizeConverter, $colorConverter, $writer); + + $formWriter = new FormWriter($mpdf, $writer); + + $form = new Form($mpdf, $otl, $colorConverter, $writer, $formWriter); + + $hyphenator = new Hyphenator($mpdf); + + $imageProcessor = new ImageProcessor( + $mpdf, + $otl, + $cssManager, + $sizeConverter, + $colorConverter, + $colorModeConverter, + $cache, + $languageToFont, + $scriptToLanguage, + $assetFetcher, + $logger + ); + + $tag = new Tag( + $mpdf, + $cache, + $cssManager, + $form, + $otl, + $tableOfContents, + $sizeConverter, + $colorConverter, + $imageProcessor, + $languageToFont + ); + + $fontWriter = new FontWriter($mpdf, $writer, $fontCache, $fontDescriptor); + $metadataWriter = new MetadataWriter($mpdf, $writer, $form, $protection, $logger); + $imageWriter = new ImageWriter($mpdf, $writer); + $pageWriter = new PageWriter($mpdf, $form, $writer, $metadataWriter); + $bookmarkWriter = new BookmarkWriter($mpdf, $writer); + $optionalContentWriter = new OptionalContentWriter($mpdf, $writer); + $colorWriter = new ColorWriter($mpdf, $writer); + $backgroundWriter = new BackgroundWriter($mpdf, $writer); + $javaScriptWriter = new JavaScriptWriter($mpdf, $writer); + + $resourceWriter = new ResourceWriter( + $mpdf, + $writer, + $colorWriter, + $fontWriter, + $imageWriter, + $formWriter, + $optionalContentWriter, + $backgroundWriter, + $bookmarkWriter, + $metadataWriter, + $javaScriptWriter, + $logger + ); + + return [ + 'otl' => $otl, + 'bmp' => $bmp, + 'cache' => $cache, + 'cssManager' => $cssManager, + 'directWrite' => $directWrite, + 'fontCache' => $fontCache, + 'fontFileFinder' => $fontFileFinder, + 'form' => $form, + 'gradient' => $gradient, + 'tableOfContents' => $tableOfContents, + 'tag' => $tag, + 'wmf' => $wmf, + 'sizeConverter' => $sizeConverter, + 'colorConverter' => $colorConverter, + 'hyphenator' => $hyphenator, + 'localContentLoader' => $localContentLoader, + 'httpClient' => $httpClient, + 'assetFetcher' => $assetFetcher, + 'imageProcessor' => $imageProcessor, + 'protection' => $protection, + + 'languageToFont' => $languageToFont, + 'scriptToLanguage' => $scriptToLanguage, + + 'writer' => $writer, + 'fontWriter' => $fontWriter, + 'metadataWriter' => $metadataWriter, + 'imageWriter' => $imageWriter, + 'formWriter' => $formWriter, + 'pageWriter' => $pageWriter, + 'bookmarkWriter' => $bookmarkWriter, + 'optionalContentWriter' => $optionalContentWriter, + 'colorWriter' => $colorWriter, + 'backgroundWriter' => $backgroundWriter, + 'javaScriptWriter' => $javaScriptWriter, + 'resourceWriter' => $resourceWriter + ]; + } + + public function getServiceIds() + { + return [ + 'otl', + 'bmp', + 'cache', + 'cssManager', + 'directWrite', + 'fontCache', + 'fontFileFinder', + 'form', + 'gradient', + 'tableOfContents', + 'tag', + 'wmf', + 'sizeConverter', + 'colorConverter', + 'hyphenator', + 'localContentLoader', + 'httpClient', + 'assetFetcher', + 'imageProcessor', + 'protection', + 'languageToFont', + 'scriptToLanguage', + 'writer', + 'fontWriter', + 'metadataWriter', + 'imageWriter', + 'formWriter', + 'pageWriter', + 'bookmarkWriter', + 'optionalContentWriter', + 'colorWriter', + 'backgroundWriter', + 'javaScriptWriter', + 'resourceWriter', + ]; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Shaper/Indic.php b/src/vendor/mpdf/mpdf/src/Shaper/Indic.php new file mode 100644 index 000000000..ab1d4bbff --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Shaper/Indic.php @@ -0,0 +1,1945 @@ +<?php + +namespace Mpdf\Shaper; + +use Mpdf\Ucdn; + +class Indic +{ + /* FROM hb-ot-shape-complex-indic-private.hh */ + + // indic_category + const OT_X = 0; + const OT_C = 1; + const OT_V = 2; + const OT_N = 3; + const OT_H = 4; + const OT_ZWNJ = 5; + const OT_ZWJ = 6; + const OT_M = 7; /* Matra or Dependent Vowel */ + const OT_SM = 8; + const OT_VD = 9; + const OT_A = 10; + const OT_NBSP = 11; + const OT_DOTTEDCIRCLE = 12; /* Not in the spec, but special in Uniscribe. /Very very/ special! */ + const OT_RS = 13; /* Register Shifter, used in Khmer OT spec */ + const OT_COENG = 14; + const OT_REPHA = 15; + + const OT_RA = 16; /* Not explicitly listed in the OT spec, but used in the grammar. */ + const OT_CM = 17; + + /* Visual positions in a syllable from left to right. */ + /* FROM hb-ot-shape-complex-indic-private.hh */ + + // indic_position + const POS_START = 0; + + const POS_RA_TO_BECOME_REPH = 1; + const POS_PRE_M = 2; + const POS_PRE_C = 3; + + const POS_BASE_C = 4; + const POS_AFTER_MAIN = 5; + + const POS_ABOVE_C = 6; + + const POS_BEFORE_SUB = 7; + const POS_BELOW_C = 8; + const POS_AFTER_SUB = 9; + + const POS_BEFORE_POST = 10; + const POS_POST_C = 11; + const POS_AFTER_POST = 12; + + const POS_FINAL_C = 13; + const POS_SMVD = 14; + + const POS_END = 15; + + /* + * Basic features. + * These features are applied in order, one at a time, after initial_reordering. + */ + + /* + * Must be in the same order as the indic_features array. Ones starting with _ are F_GLOBAL + * Ones without the _ are only applied where the mask says! + */ + + const _NUKT = 0; + const _AKHN = 1; + const RPHF = 2; + const _RKRF = 3; + const PREF = 4; + const BLWF = 5; + const HALF = 6; + const ABVF = 7; + const PSTF = 8; + const CFAR = 9; // Khmer only + const _VATU = 10; + const _CJCT = 11; + const INIT = 12; + + // Based on indic_category used to make string to find syllables + // OT_ to string character (using e.g. OT_C from INDIC) hb-ot-shape-complex-indic-private.hh + public static $indic_category_char = [ + 'x', + 'C', + 'V', + 'N', + 'H', + 'Z', + 'J', + 'M', + 'S', + 'v', + 'A', /* Spec gives Andutta U+0952 as OT_A. However, testing shows that Uniscribe + * treats U+0951..U+0952 all as OT_VD - see set_indic_properties */ + 's', + 'D', + 'F', /* Register shift Khmer only */ + 'G', /* Khmer only */ + 'r', /* 0D4E (dot reph) only one in Malayalam */ + 'R', + 'm', /* Consonant medial only used in Indic 0A75 in Gurmukhi (0A00..0A7F) : also in Lao, Myanmar, Tai Tham, Javanese & Cham */ + ]; + + public static function set_indic_properties(&$info, $scriptblock) + { + $u = $info['uni']; + $type = self::indic_get_categories($u); + $cat = ($type & 0x7F); + $pos = ($type >> 8); + + /* + * Re-assign category + */ + + if ($u == 0x17D1) { + $cat = self::OT_X; + } + + if ($cat == self::OT_X && self::in_range($u, 0x17CB, 0x17D3)) { /* Khmer Various signs */ + /* These are like Top Matras. */ + $cat = self::OT_M; + $pos = self::POS_ABOVE_C; + } + + if ($u == 0x17C6) { + $cat = self::OT_N; + } /* Khmer Bindu doesn't like to be repositioned. */ + + if ($u == 0x17D2) { + $cat = self::OT_COENG; + } /* Khmer coeng */ + + /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe + * treats U+0951..U+0952 all as OT_VD. + * TESTS: + * U+092E,U+0947,U+0952 + * U+092E,U+0952,U+0947 + * U+092E,U+0947,U+0951 + * U+092E,U+0951,U+0947 + * */ + //if ($u == 0x0952) $cat = self::OT_A; + if (self::in_range($u, 0x0951, 0x0954)) { + $cat = self::OT_VD; + } + + if ($u == 0x200C) { + $cat = self::OT_ZWNJ; + } elseif ($u == 0x200D) { + $cat = self::OT_ZWJ; + } elseif ($u == 0x25CC) { + $cat = self::OT_DOTTEDCIRCLE; + } elseif ($u == 0x0A71) { + $cat = self::OT_SM; + } /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */ + + if ($cat == self::OT_REPHA) { + /* There are two kinds of characters marked as Repha: + * - The ones that are GenCat=Mn are already positioned visually, ie. after base. (eg. Khmer) + * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syllable. (eg. Malayalam) + * + * We recategorize the first kind to look like a Nukta and attached to the base directly. + */ + if ($info['general_category'] == Ucdn::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + $cat = self::OT_N; + } + } + + /* + * Re-assign position. + */ + + if ((self::FLAG($cat) & (self::FLAG(self::OT_C) | self::FLAG(self::OT_CM) | self::FLAG(self::OT_RA) | self::FLAG(self::OT_V) | self::FLAG(self::OT_NBSP) | self::FLAG(self::OT_DOTTEDCIRCLE)))) { // = CONSONANT_FLAGS like is_consonant + if ($scriptblock == Ucdn::SCRIPT_KHMER) { + $pos = self::POS_BELOW_C; + } /* Khmer differs from Indic here. */ + else { + $pos = self::POS_BASE_C; + } /* Will recategorize later based on font lookups. */ + + if (self::is_ra($u)) { + $cat = self::OT_RA; + } + } elseif ($cat == self::OT_M) { + $pos = self::matra_position($u, $pos); + } elseif ($cat == self::OT_SM || $cat == self::OT_VD) { + $pos = self::POS_SMVD; + } + + if ($u == 0x0B01) { + $pos = self::POS_BEFORE_SUB; + } /* Oriya Bindu is BeforeSub in the spec. */ + + $info['indic_category'] = $cat; + $info['indic_position'] = $pos; + } + + // syllable_type + const CONSONANT_SYLLABLE = 0; + const VOWEL_SYLLABLE = 1; + const STANDALONE_CLUSTER = 2; + const BROKEN_CLUSTER = 3; + const NON_INDIC_CLUSTER = 4; + + public static function set_syllables(&$o, $s, &$broken_syllables) + { + $ptr = 0; + $syllable_serial = 1; + $broken_syllables = false; + + while ($ptr < strlen($s)) { + $match = ''; + $syllable_length = 1; + $syllable_type = self::NON_INDIC_CLUSTER; + // CONSONANT_SYLLABLE Consonant syllable + // From OT spec: + if (preg_match('/^([CR]m*[N]?(H[ZJ]?|[ZJ]H))*[CR]m*[N]?[A]?(H[ZJ]?|[M]*[N]?[H]?)?[S]?[v]{0,2}/', substr($s, $ptr), $ma)) { + // From HarfBuzz: + //if (preg_match('/^r?([CR]J?(Z?[N]{0,2})?[ZJ]?H(J[N]?)?){0,4}[CR]J?(Z?[N]{0,2})?A?((([ZJ]?H(J[N]?)?)|HZ)|(HJ)?([ZJ]{0,3}M[N]?(H|JHJR)?){0,4})?(S[Z]?)?[v]{0,2}/', substr($s,$ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::CONSONANT_SYLLABLE; + } // VOWEL_SYLLABLE Vowel-based syllable + // From OT spec: + elseif (preg_match('/^(RH|r)?V[N]?([ZJ]?H[CR]m*|J[CR]m*)?([M]*[N]?[H]?)?[S]?[v]{0,2}/', substr($s, $ptr), $ma)) { + // From HarfBuzz: + //else if (preg_match('/^(RH|r)?V(Z?[N]{0,2})?(J|([ZJ]?H(J[N]?)?[CR]J?(Z?[N]{0,2})?){0,4}((([ZJ]?H(J[N]?)?)|HZ)|(HJ)?([ZJ]{0,3}M[N]?(H|JHJR)?){0,4})?(S[Z]?)?[v]{0,2})/', substr($s,$ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::VOWEL_SYLLABLE; + } /* Apply only if it's a word start. */ + // STANDALONE_CLUSTER Stand Alone syllable at start of word + // From OT spec: + elseif (($ptr == 0 || + $o[$ptr - 1]['general_category'] < Ucdn::UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER || + $o[$ptr - 1]['general_category'] > Ucdn::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK + ) && (preg_match('/^(RH|r)?[sD][N]?([ZJ]?H[CR]m*)?([M]*[N]?[H]?)?[S]?[v]{0,2}/', substr($s, $ptr), $ma))) { + // From HarfBuzz: + // && (preg_match('/^(RH|r)?[sD](Z?[N]{0,2})?(([ZJ]?H(J[N]?)?)[CR]J?(Z?[N]{0,2})?){0,4}((([ZJ]?H(J[N]?)?)|HZ)|(HJ)?([ZJ]{0,3}M[N]?(H|JHJR)?){0,4})?(S[Z]?)?[v]{0,2}/', substr($s,$ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::STANDALONE_CLUSTER; + } // BROKEN_CLUSTER syllable + elseif (preg_match('/^(RH|r)?[N]?([ZJ]?H[CR])?([M]*[N]?[H]?)?[S]?[v]{0,2}/', substr($s, $ptr), $ma)) { + // From HarfBuzz: + //else if (preg_match('/^(RH|r)?(Z?[N]{0,2})?(([ZJ]?H(J[N]?)?)[CR]J?(Z?[N]{0,2})?){0,4}((([ZJ]?H(J[N]?)?)|HZ)|(HJ)?([ZJ]{0,3}M[N]?(H|JHJR)?){0,4})(S[Z]?)?[v]{0,2}/', substr($s,$ptr), $ma)) { + if (strlen($ma[0])) { // May match blank + $syllable_length = strlen($ma[0]); + $syllable_type = self::BROKEN_CLUSTER; + $broken_syllables = true; + } + } + + for ($i = $ptr; $i < $ptr + $syllable_length; $i++) { + $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type; + } + $ptr += $syllable_length; + $syllable_serial++; + if ($syllable_serial == 16) { + $syllable_serial = 1; + } + } + } + + public static function set_syllables_sinhala(&$o, $s, &$broken_syllables) + { + $ptr = 0; + $syllable_serial = 1; + $broken_syllables = false; + + while ($ptr < strlen($s)) { + $match = ''; + $syllable_length = 1; + $syllable_type = self::NON_INDIC_CLUSTER; + // CONSONANT_SYLLABLE Consonant syllable + // From OT spec: + if (preg_match('/^([CR]HJ|[CR]JH){0,8}[CR][HM]{0,3}[S]{0,1}/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::CONSONANT_SYLLABLE; + } // VOWEL_SYLLABLE Vowel-based syllable + // From OT spec: + elseif (preg_match('/^V[S]{0,1}/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::VOWEL_SYLLABLE; + } + + for ($i = $ptr; $i < $ptr + $syllable_length; $i++) { + $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type; + } + $ptr += $syllable_length; + $syllable_serial++; + if ($syllable_serial == 16) { + $syllable_serial = 1; + } + } + } + + public static function set_syllables_khmer(&$o, $s, &$broken_syllables) + { + $ptr = 0; + $syllable_serial = 1; + $broken_syllables = false; + + while ($ptr < strlen($s)) { + $match = ''; + $syllable_length = 1; + $syllable_type = self::NON_INDIC_CLUSTER; + // CONSONANT_SYLLABLE Consonant syllable + if (preg_match('/^r?([CR]J?((Z?F)?[N]{0,2})?[ZJ]?G(JN?)?){0,4}[CR]J?((Z?F)?[N]{0,2})?A?((([ZJ]?G(JN?)?)|GZ)|(GJ)?([ZJ]{0,3}MN?(H|JHJR)?){0,4})?(G([CR]J?((Z?F)?[N]{0,2})?|V))?(SZ?)?[v]{0,2}/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::CONSONANT_SYLLABLE; + } // VOWEL_SYLLABLE Vowel-based syllable + elseif (preg_match('/^(RH|r)?V((Z?F)?[N]{0,2})?(J|([ZJ]?G(JN?)?[CR]J?((Z?F)?[N]{0,2})?){0,4}((([ZJ]?G(JN?)?)|GZ)|(GJ)?([ZJ]{0,3}MN?(H|JHJR)?){0,4})?(G([CR]J?((Z?F)?[N]{0,2})?|V))?(SZ?)?[v]{0,2})/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::VOWEL_SYLLABLE; + } // BROKEN_CLUSTER syllable + elseif (preg_match('/^(RH|r)?((Z?F)?[N]{0,2})?(([ZJ]?G(JN?)?)[CR]J?((Z?F)?[N]{0,2})?){0,4}((([ZJ]?G(JN?)?)|GZ)|(GJ)?([ZJ]{0,3}MN?(H|JHJR)?){0,4})(G([CR]J?((Z?F)?[N]{0,2})?|V))?(SZ?)?[v]{0,2}/', substr($s, $ptr), $ma)) { + if (strlen($ma[0])) { // May match blank + $syllable_length = strlen($ma[0]); + $syllable_type = self::BROKEN_CLUSTER; + $broken_syllables = true; + } + } + + for ($i = $ptr; $i < $ptr + $syllable_length; $i++) { + $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type; + } + $ptr += $syllable_length; + $syllable_serial++; + if ($syllable_serial == 16) { + $syllable_serial = 1; + } + } + } + + public static function initial_reordering(&$info, $GSUBdata, $broken_syllables, $indic_config, $scriptblock, $is_old_spec, $dottedcircle) + { + + self::update_consonant_positions($info, $GSUBdata); + + if ($broken_syllables && $dottedcircle) { + self::insert_dotted_circles($info, $dottedcircle); + } + + $count = count($info); + if (!$count) { + return; + } + $last = 0; + $last_syllable = $info[0]['syllable']; + for ($i = 1; $i < $count; $i++) { + if ($last_syllable != $info[$i]['syllable']) { + self::initial_reordering_syllable($info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $last, $i); + $last = $i; + $last_syllable = $info[$last]['syllable']; + } + } + self::initial_reordering_syllable($info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $last, $count); + } + + public static function update_consonant_positions(&$info, $GSUBdata) + { + $count = count($info); + for ($i = 0; $i < $count; $i++) { + if ($info[$i]['indic_position'] == self::POS_BASE_C) { + $c = $info[$i]['uni']; + // If would substitute... + if (isset($GSUBdata['pref'][$c])) { + $info[$i]['indic_position'] = self::POS_POST_C; + } elseif (isset($GSUBdata['blwf'][$c])) { + $info[$i]['indic_position'] = self::POS_BELOW_C; + } elseif (isset($GSUBdata['pstf'][$c])) { + $info[$i]['indic_position'] = self::POS_POST_C; + } + } + } + } + + public static function insert_dotted_circles(&$info, $dottedcircle) + { + $idx = 0; + $last_syllable = 0; + while ($idx < count($info)) { + $syllable = $info[$idx]['syllable']; + $syllable_type = ($syllable & 0x0F); + if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) { + $last_syllable = $syllable; + + $dottedcircle[0]['syllable'] = $info[$idx]['syllable']; + + /* Insert dottedcircle after possible Repha. */ + while ($idx < count($info) && $last_syllable == $info[$idx]['syllable'] && $info[$idx]['indic_category'] == self::OT_REPHA) { + $idx++; + } + array_splice($info, $idx, 0, $dottedcircle); + } else { + $idx++; + } + } + + // I am not sue how this code below got in here, since $idx should now be > count($info) and thus invalid. + // In case I am missing something(!) I'll leave a warning here for now: + if (isset($info[$idx])) { + throw new \Mpdf\MpdfException('Unexpected error occurred in Indic processing'); + } + // In case of final bloken cluster... + //$syllable = $info[$idx]['syllable']; + //$syllable_type = ($syllable & 0x0F); + //if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) { + // $dottedcircle[0]['syllable'] = $info[$idx]['syllable']; + // array_splice($info, $idx, 0, $dottedcircle); + //} + } + + /* Rules from: + * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */ + + public static function initial_reordering_syllable(&$info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $start, $end) + { + /* vowel_syllable: We made the vowels look like consonants. So uses the consonant logic! */ + /* broken_cluster: We already inserted dotted-circles, so just call the standalone_cluster. */ + /* standalone_cluster: We treat NBSP/dotted-circle as if they are consonants, so we should just chain. */ + + $syllable_type = ($info[$start]['syllable'] & 0x0F); + if ($syllable_type == self::NON_INDIC_CLUSTER) { + return; + } + if ($syllable_type == self::BROKEN_CLUSTER || $syllable_type == self::STANDALONE_CLUSTER) { + //if ($uniscribe_bug_compatible) { + /* For dotted-circle, this is what Uniscribe does: + * If dotted-circle is the last glyph, it just does nothing. + * i.e. It doesn't form Reph. */ + if ($info[$end - 1]['indic_category'] == self::OT_DOTTEDCIRCLE) { + return; + } + } + + /* 1. Find base consonant: + * + * The shaping engine finds the base consonant of the syllable, using the + * following algorithm: starting from the end of the syllable, move backwards + * until a consonant is found that does not have a below-base or post-base + * form (post-base forms have to follow below-base forms), or that is not a + * pre-base reordering Ra, or arrive at the first consonant. The consonant + * stopped at will be the base. + * + * o If the syllable starts with Ra + Halant (in a script that has Reph) + * and has more than one consonant, Ra is excluded from candidates for + * base consonants. + */ + + $base = $end; + $has_reph = false; + $limit = $start; + + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + /* -> If the syllable starts with Ra + Halant (in a script that has Reph) + * and has more than one consonant, Ra is excluded from candidates for + * base consonants. */ + if (count($GSUBdata['rphf']) /* ?? $indic_plan->mask_array[RPHF] */ && $start + 3 <= $end && + ( + ($indic_config[4] == self::REPH_MODE_IMPLICIT && !self::is_joiner($info[$start + 2])) || + ($indic_config[4] == self::REPH_MODE_EXPLICIT && $info[$start + 2]['indic_category'] == self::OT_ZWJ) + )) { + /* See if it matches the 'rphf' feature. */ + //$glyphs = array($info[$start]['uni'], $info[$start + 1]['uni']); + //if ($indic_plan->rphf->would_substitute ($glyphs, count($glyphs), true, face)) { + if (isset($GSUBdata['rphf'][$info[$start]['uni']]) && self::is_halant_or_coeng($info[$start + 1])) { + $limit += 2; + while ($limit < $end && self::is_joiner($info[$limit])) { + $limit++; + } + $base = $start; + $has_reph = true; + } + } elseif ($indic_config[4] == self::REPH_MODE_LOG_REPHA && $info[$start]['indic_category'] == self::OT_REPHA) { + $limit += 1; + while ($limit < $end && self::is_joiner($info[$limit])) { + $limit++; + } + $base = $start; + $has_reph = true; + } + } + + switch ($indic_config[2]) { // base_pos + case self::BASE_POS_LAST: + /* -> starting from the end of the syllable, move backwards */ + $i = $end; + $seen_below = false; + do { + $i--; + /* -> until a consonant is found */ + if (self::is_consonant($info[$i])) { + /* -> that does not have a below-base or post-base form + * (post-base forms have to follow below-base forms), */ + if ($info[$i]['indic_position'] != self::POS_BELOW_C && ($info[$i]['indic_position'] != self::POS_POST_C || $seen_below)) { + $base = $i; + break; + } + if ($info[$i]['indic_position'] == self::POS_BELOW_C) { + $seen_below = true; + } + + /* -> or that is not a pre-base reordering Ra, + * + * IMPLEMENTATION NOTES: + * + * Our pre-base reordering Ra's are marked POS_POST_C, so will be skipped + * by the logic above already. + */ + + /* -> or arrive at the first consonant. The consonant stopped at will + * be the base. */ + $base = $i; + } else { + /* A ZWJ after a Halant stops the base search, and requests an explicit + * half form. + * [A ZWJ before a Halant, requests a subjoined form instead, and hence + * search continues. This is particularly important for Bengali + * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya] */ + if ($start < $i && $info[$i]['indic_category'] == self::OT_ZWJ && $info[$i - 1]['indic_category'] == self::OT_H) { + if (!defined("OMIT_INDIC_FIX_1") || OMIT_INDIC_FIX_1 != 1) { + $base = $i; + } // INDIC_FIX_1 + break; + } + // ZKI8 + if ($start < $i && $info[$i]['indic_category'] == self::OT_ZWNJ) { + break; + } + } + } while ($i > $limit); + break; + + case self::BASE_POS_FIRST: + /* In scripts without half forms (eg. Khmer), the first consonant is always the base. */ + + if (!$has_reph) { + $base = $limit; + } + + /* Find the last base consonant that is not blocked by ZWJ. If there is + * a ZWJ right before a base consonant, that would request a subjoined form. */ + for ($i = $limit; $i < $end; $i++) { + if (self::is_consonant($info[$i]) && $info[$i]['indic_position'] == self::POS_BASE_C) { + if ($limit < $i && $info[$i - 1]['indic_category'] == self::OT_ZWJ) { + break; + } else { + $base = $i; + } + } + } + + /* Mark all subsequent consonants as below. */ + for ($i = $base + 1; $i < $end; $i++) { + if (self::is_consonant($info[$i]) && $info[$i]['indic_position'] == self::POS_BASE_C) { + $info[$i]['indic_position'] = self::POS_BELOW_C; + } + } + break; + //default: + //assert (false); + /* fallthrough */ + } + + /* -> If the syllable starts with Ra + Halant (in a script that has Reph) + * and has more than one consonant, Ra is excluded from candidates for + * base consonants. + * + * Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */ + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + if ($has_reph && $base == $start && $limit - $base <= 2) { + /* Have no other consonant, so Reph is not formed and Ra becomes base. */ + $has_reph = false; + } + } + + /* 2. Decompose and reorder Matras: + * + * Each matra and any syllable modifier sign in the cluster are moved to the + * appropriate position relative to the consonant(s) in the cluster. The + * shaping engine decomposes two- or three-part matras into their constituent + * parts before any repositioning. Matra characters are classified by which + * consonant in a conjunct they have affinity for and are reordered to the + * following positions: + * + * o Before first half form in the syllable + * o After subjoined consonants + * o After post-form consonant + * o After main consonant (for above marks) + * + * IMPLEMENTATION NOTES: + * + * The normalize() routine has already decomposed matras for us, so we don't + * need to worry about that. + */ + + + /* 3. Reorder marks to canonical order: + * + * Adjacent nukta and halant or nukta and vedic sign are always repositioned + * if necessary, so that the nukta is first. + * + * IMPLEMENTATION NOTES: + * + * Use the combining Class from Unicode categories? to bubble_sort. + */ + + /* Reorder characters */ + + for ($i = $start; $i < $base; $i++) { + $info[$i]['indic_position'] = min(self::POS_PRE_C, $info[$i]['indic_position']); + } + + if ($base < $end) { + $info[$base]['indic_position'] = self::POS_BASE_C; + } + + /* Mark final consonants. A final consonant is one appearing after a matra, + * ? only in Khmer. */ + for ($i = $base + 1; $i < $end; $i++) { + if ($info[$i]['indic_category'] == self::OT_M) { + for ($j = $i + 1; $j < $end; $j++) { + if (self::is_consonant($info[$j])) { + $info[$j]['indic_position'] = self::POS_FINAL_C; + break; + } + } + break; + } + } + + /* Handle beginning Ra */ + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + if ($has_reph) { + $info[$start]['indic_position'] = self::POS_RA_TO_BECOME_REPH; + } + } + + + /* For old-style Indic script tags, move the first post-base Halant after + * last consonant. Only do this if there is *not* a Halant after last + * consonant. Otherwise it becomes messy. */ + if ($is_old_spec) { + for ($i = $base + 1; $i < $end; $i++) { + if ($info[$i]['indic_category'] == self::OT_H) { + for ($j = $end - 1; $j > $i; $j--) { + if (self::is_consonant($info[$j]) || $info[$j]['indic_category'] == self::OT_H) { + break; + } + } + if ($info[$j]['indic_category'] != self::OT_H && $j > $i) { + /* Move Halant to after last consonant. */ + self::_move_info_pos($info, $i, $j + 1); + } + break; + } + } + } + + /* Attach misc marks to previous char to move with them. */ + $last_pos = self::POS_START; + for ($i = $start; $i < $end; $i++) { + if ((self::FLAG($info[$i]['indic_category']) & (self::FLAG(self::OT_ZWJ) | self::FLAG(self::OT_ZWNJ) | self::FLAG(self::OT_N) | self::FLAG(self::OT_RS) | self::FLAG(self::OT_H) | self::FLAG(self::OT_COENG) ))) { + $info[$i]['indic_position'] = $last_pos; + if ($info[$i]['indic_category'] == self::OT_H && $info[$i]['indic_position'] == self::POS_PRE_M) { + /* + * Uniscribe doesn't move the Halant with Left Matra. + * TEST: U+092B,U+093F,U+094DE + * We follow. This is important for the Sinhala + * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA + * where U+0DD9 is a left matra and U+0DCA is the virama. + * We don't want to move the virama with the left matra. + * TEST: U+0D9A,U+0DDA + */ + for ($j = $i; $j > $start; $j--) { + if ($info[$j - 1]['indic_position'] != self::POS_PRE_M) { + $info[$i]['indic_position'] = $info[$j - 1]['indic_position']; + break; + } + } + } + } elseif ($info[$i]['indic_position'] != self::POS_SMVD) { + $last_pos = $info[$i]['indic_position']; + } + } + + /* Re-attach ZWJ, ZWNJ, and halant to next char, for after-base consonants. */ + $last_halant = $end; + for ($i = $base + 1; $i < $end; $i++) { + if (self::is_halant_or_coeng($info[$i])) { + $last_halant = $i; + } elseif (self::is_consonant($info[$i])) { + for ($j = $last_halant; $j < $i; $j++) { + if ($info[$j]['indic_position'] != self::POS_SMVD) { + $info[$j]['indic_position'] = $info[$i]['indic_position']; + } + } + } + } + + + if ($scriptblock == Ucdn::SCRIPT_KHMER) { + /* KHMER_FIX_2 */ + /* Move Coeng+RO (Halant,Ra) sequence before base consonant. */ + for ($i = $base + 1; $i < $end; $i++) { + if (self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni'])) { + $info[$i]['indic_position'] = self::POS_PRE_C; + $info[$i + 1]['indic_position'] = self::POS_PRE_C; + break; + } + } + } + + + /* + if (!defined("OMIT_INDIC_FIX_2") || OMIT_INDIC_FIX_2 != 1) { + // INDIC_FIX_2 + $ZWNJ_found = false; + $POST_ZWNJ_c_found = false; + for ($i = $base + 1; $i < $end; $i++) { + if ($info[$i]['indic_category'] == self::OT_ZWNJ) { $ZWNJ_found = true; } + else if ($ZWNJ_found && $info[$i]['indic_category'] == self::OT_C) { $POST_ZWNJ_c_found = true; } + else if ($POST_ZWNJ_c_found && $info[$i]['indic_position'] == self::POS_BEFORE_SUB) { $info[$i]['indic_position'] = self::POS_AFTER_SUB; } + } + } + */ + + /* Setup masks now */ + for ($i = $start; $i < $end; $i++) { + $info[$i]['mask'] = 0; + } + + + if ($scriptblock == Ucdn::SCRIPT_KHMER) { + /* Find a Coeng+RO (Halant,Ra) sequence and mark it for pre-base processing. */ + $mask = self::FLAG(self::PREF); + for ($i = $base; $i < $end - 1; $i++) { /* KHMER_FIX_1 From $start (not base) */ + if (self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni'])) { + $info[$i]['mask'] |= self::FLAG(self::PREF); + $info[$i + 1]['mask'] |= self::FLAG(self::PREF); + + /* Mark the subsequent stuff with 'cfar'. Used in Khmer. + * Read the feature spec. + * This allows distinguishing the following cases with MS Khmer fonts: + * U+1784,U+17D2,U+179A,U+17D2,U+1782 [C+Coeng+RO+Coeng+C] => Should activate CFAR + * U+1784,U+17D2,U+1782,U+17D2,U+179A [C+Coeng+C+Coeng+RO] => Should NOT activate CFAR + */ + for ($j = ($i + 2); $j < $end; $j++) { + $info[$j]['mask'] |= self::FLAG(self::CFAR); + } + + break; + } + } + } + + + + /* Sit tight, rock 'n roll! */ + self::bubble_sort($info, $start, $end - $start); + + /* Find base again */ + $base = $end; + for ($i = $start; $i < $end; $i++) { + if ($info[$i]['indic_position'] == self::POS_BASE_C) { + $base = $i; + break; + } + } + + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + /* Reph */ + for ($i = $start; $i < $end; $i++) { + if ($info[$i]['indic_position'] == self::POS_RA_TO_BECOME_REPH) { + $info[$i]['mask'] |= self::FLAG(self::RPHF); + } + } + + /* Pre-base */ + $mask = self::FLAG(self::HALF); + for ($i = $start; $i < $base; $i++) { + $info[$i]['mask'] |= $mask; + } + } + + /* Post-base */ + $mask = (self::FLAG(self::BLWF) | self::FLAG(self::ABVF) | self::FLAG(self::PSTF)); + for ($i = $base + 1; $i < $end; $i++) { + $info[$i]['mask'] |= $mask; + } + + + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + if (!defined("OMIT_INDIC_FIX_3") || OMIT_INDIC_FIX_3 != 1) { + /* INDIC_FIX_3 */ + /* Find a (pre-base) Consonant, Halant,Ra sequence and mark Halant|Ra for below-base BLWF processing. */ + // TEST CASE ক্র্ক in FreeSans versus Vrinda + if (($base - $start) >= 3) { + for ($i = $start; $i < ($base - 2); $i++) { + if (self::is_consonant($info[$i])) { + if (self::is_halant_or_coeng($info[$i + 1]) && self::is_ra($info[$i + 2]['uni'])) { + // If would substitute Halant+Ra...BLWF + if (isset($GSUBdata['blwf'][$info[$i + 2]['uni']])) { + $info[$i + 1]['mask'] |= self::FLAG(self::BLWF); + $info[$i + 2]['mask'] |= self::FLAG(self::BLWF); + } /* If would not substitute as blwf, mark Ra+Halant for RPHF using following Halant (if present) */ elseif (self::is_halant_or_coeng($info[$i + 3])) { + $info[$i + 2]['mask'] |= self::FLAG(self::RPHF); + $info[$i + 3]['mask'] |= self::FLAG(self::RPHF); + } + break; + } + } + } + } + } + } + + + + if ($is_old_spec && $scriptblock == Ucdn::SCRIPT_DEVANAGARI) { + /* Old-spec eye-lash Ra needs special handling. From the spec: + * "The feature 'below-base form' is applied to consonants + * having below-base forms and following the base consonant. + * The exception is vattu, which may appear below half forms + * as well as below the base glyph. The feature 'below-base + * form' will be applied to all such occurrences of Ra as well." + * + * Test case: U+0924,U+094D,U+0930,U+094d,U+0915 + * with Sanskrit 2003 font. + * + * However, note that Ra,Halant,ZWJ is the correct way to + * request eyelash form of Ra, so we wouldbn't inhibit it + * in that sequence. + * + * Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915 + */ + for ($i = $start; ($i + 1) < $base; $i++) { + if ($info[$i]['indic_category'] == self::OT_RA && $info[$i + 1]['indic_category'] == self::OT_H && + ($i + 2 == $base || $info[$i + 2]['indic_category'] != self::OT_ZWJ)) { + $info[$i]['mask'] |= self::FLAG(self::BLWF); + $info[$i + 1]['mask'] |= self::FLAG(self::BLWF); + } + } + } + + if ($scriptblock != Ucdn::SCRIPT_KHMER) { + if (count($GSUBdata['pref']) && $base + 2 < $end) { + /* Find a Halant,Ra sequence and mark it for pre-base processing. */ + for ($i = $base + 1; $i + 1 < $end; $i++) { + // If old_spec find Ra-Halant... + if ((isset($GSUBdata['pref'][$info[$i + 1]['uni']]) && self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni']) ) || + ($is_old_spec && isset($GSUBdata['pref'][$info[$i]['uni']]) && self::is_halant_or_coeng($info[$i + 1]) && self::is_ra($info[$i]['uni']) ) + ) { + $info[$i++]['mask'] |= self::FLAG(self::PREF); + $info[$i++]['mask'] |= self::FLAG(self::PREF); + break; + } + } + } + } + + + /* Apply ZWJ/ZWNJ effects */ + for ($i = $start + 1; $i < $end; $i++) { + if (self::is_joiner($info[$i])) { + $non_joiner = ($info[$i]['indic_category'] == self::OT_ZWNJ); + $j = $i; + while ($j > $start) { + if (defined("OMIT_INDIC_FIX_4") && OMIT_INDIC_FIX_4 == 1) { + // INDIC_FIX_4 = do nothing - carry on // + // ZWNJ should block H C from forming blwf post-base - need to unmask backwards beyond first consonant arrived at // + if (!self::is_consonant($info[$j])) { + break; + } + } + $j--; + + /* ZWJ/ZWNJ should disable CJCT. They do that by simply + * being there, since we don't skip them for the CJCT + * feature (ie. F_MANUAL_ZWJ) */ + + /* A ZWNJ disables HALF. */ + if ($non_joiner) { + $info[$j]['mask'] &= ~(self::FLAG(self::HALF) | self::FLAG(self::BLWF)); + } + } + } + } + } + + public static function final_reordering(&$info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec) + { + $count = count($info); + if (!$count) { + return; + } + $last = 0; + $last_syllable = $info[0]['syllable']; + for ($i = 1; $i < $count; $i++) { + if ($last_syllable != $info[$i]['syllable']) { + self::final_reordering_syllable($info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $last, $i); + $last = $i; + $last_syllable = $info[$last]['syllable']; + } + } + self::final_reordering_syllable($info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $last, $count); + } + + public static function final_reordering_syllable(&$info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $start, $end) + { + + /* 4. Final reordering: + * + * After the localized forms and basic shaping forms GSUB features have been + * applied (see below), the shaping engine performs some final glyph + * reordering before applying all the remaining font features to the entire + * cluster. + */ + + /* Find base again */ + for ($base = $start; $base < $end; $base++) { + if ($info[$base]['indic_position'] >= self::POS_BASE_C) { + if ($start < $base && $info[$base]['indic_position'] > self::POS_BASE_C) { + $base--; + } + break; + } + } + if ($base == $end && $start < $base && $info[$base - 1]['indic_category'] != self::OT_ZWJ) { + $base--; + } + while ($start < $base && isset($info[$base]) && ($info[$base]['indic_category'] == self::OT_H || $info[$base]['indic_category'] == self::OT_N)) { + $base--; + } + + + /* o Reorder matras: + * + * If a pre-base matra character had been reordered before applying basic + * features, the glyph can be moved closer to the main consonant based on + * whether half-forms had been formed. Actual position for the matra is + * defined as "after last standalone halant glyph, after initial matra + * position and before the main consonant". If ZWJ or ZWNJ follow this + * halant, position is moved after it. + */ + + + if ($start + 1 < $end && $start < $base) { /* Otherwise there can't be any pre-base matra characters. */ + /* If we lost track of base, alas, position before last thingy. */ + $new_pos = ($base == $end) ? $base - 2 : $base - 1; + + /* Malayalam / Tamil do not have "half" forms or explicit virama forms. + * The glyphs formed by 'half' are Chillus or ligated explicit viramas. + * We want to position matra after them. + */ + if ($scriptblock != Ucdn::SCRIPT_MALAYALAM && $scriptblock != Ucdn::SCRIPT_TAMIL) { + while ($new_pos > $start && !(self::is_one_of($info[$new_pos], (self::FLAG(self::OT_M) | self::FLAG(self::OT_H) | self::FLAG(self::OT_COENG))))) { + $new_pos--; + } + + /* If we found no Halant we are done. + * Otherwise only proceed if the Halant does + * not belong to the Matra itself! */ + if (self::is_halant_or_coeng($info[$new_pos]) && $info[$new_pos]['indic_position'] != self::POS_PRE_M) { + /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ + if ($new_pos + 1 < $end && self::is_joiner($info[$new_pos + 1])) { + $new_pos++; + } + } else { + $new_pos = $start; + } /* No move. */ + } + + if ($start < $new_pos && $info[$new_pos]['indic_position'] != self::POS_PRE_M) { + /* Now go see if there's actually any matras... */ + for ($i = $new_pos; $i > $start; $i--) { + if ($info[$i - 1]['indic_position'] == self::POS_PRE_M) { + $old_pos = $i - 1; + //memmove (&info[$old_pos], &info[$old_pos + 1], ($new_pos - $old_pos) * sizeof ($info[0])); + self::_move_info_pos($info, $old_pos, $new_pos + 1); + + if ($old_pos < $base && $base <= $new_pos) { /* Shouldn't actually happen. */ + $base--; + } + $new_pos--; + } + } + } + } + + + /* o Reorder reph: + * + * Reph's original position is always at the beginning of the syllable, + * (i.e. it is not reordered at the character reordering stage). However, + * it will be reordered according to the basic-forms shaping results. + * Possible positions for reph, depending on the script, are; after main, + * before post-base consonant forms, and after post-base consonant forms. + */ + + /* If there's anything after the Ra that has the REPH pos, it ought to be halant. + * Which means that the font has failed to ligate the Reph. In which case, we + * shouldn't move. */ + if ($start + 1 < $end && + $info[$start]['indic_position'] == self::POS_RA_TO_BECOME_REPH && $info[$start + 1]['indic_position'] != self::POS_RA_TO_BECOME_REPH) { + $reph_pos = $indic_config[3]; + $skip_to_reph_step_5 = false; + $skip_to_reph_move = false; + + /* 1. If reph should be positioned after post-base consonant forms, + * proceed to step 5. + */ + if ($reph_pos == self::REPH_POS_AFTER_POST) { + $skip_to_reph_step_5 = true; + } + + /* 2. If the reph repositioning class is not after post-base: target + * position is after the first explicit halant glyph between the + * first post-reph consonant and last main consonant. If ZWJ or ZWNJ + * are following this halant, position is moved after it. If such + * position is found, this is the target position. Otherwise, + * proceed to the next step. + * + * Note: in old-implementation fonts, where classifications were + * fixed in shaping engine, there was no case where reph position + * will be found on this step. + */ + + if (!$skip_to_reph_step_5) { + $new_reph_pos = $start + 1; + + while ($new_reph_pos < $base && !self::is_halant_or_coeng($info[$new_reph_pos])) { + $new_reph_pos++; + } + + if ($new_reph_pos < $base && self::is_halant_or_coeng($info[$new_reph_pos])) { + /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */ + if ($new_reph_pos + 1 < $base && self::is_joiner($info[$new_reph_pos + 1])) { + $new_reph_pos++; + } + $skip_to_reph_move = true; + } + } + + /* 3. If reph should be repositioned after the main consonant: find the + * first consonant not ligated with main, or find the first + * consonant that is not a potential pre-base reordering Ra. + */ + if ($reph_pos == self::REPH_POS_AFTER_MAIN && !$skip_to_reph_move && !$skip_to_reph_step_5) { + $new_reph_pos = $base; + /* XXX Skip potential pre-base reordering Ra. */ + while ($new_reph_pos + 1 < $end && $info[$new_reph_pos + 1]['indic_position'] <= self::POS_AFTER_MAIN) { + $new_reph_pos++; + } + if ($new_reph_pos < $end) { + $skip_to_reph_move = true; + } + } + + /* 4. If reph should be positioned before post-base consonant, find + * first post-base classified consonant not ligated with main. If no + * consonant is found, the target position should be before the + * first matra, syllable modifier sign or vedic sign. + */ + /* This is our take on what step 4 is trying to say (and failing, BADLY). */ + if ($reph_pos == self::REPH_POS_AFTER_SUB && !$skip_to_reph_move && !$skip_to_reph_step_5) { + $new_reph_pos = $base; + while ($new_reph_pos < $end && isset($info[$new_reph_pos + 1]['indic_position']) && + !( self::FLAG($info[$new_reph_pos + 1]['indic_position']) & (self::FLAG(self::POS_POST_C) | self::FLAG(self::POS_AFTER_POST) | self::FLAG(self::POS_SMVD)))) { + $new_reph_pos++; + } + if ($new_reph_pos < $end) { + $skip_to_reph_move = true; + } + } + + /* 5. If no consonant is found in steps 3 or 4, move reph to a position + * immediately before the first post-base matra, syllable modifier + * sign or vedic sign that has a reordering class after the intended + * reph position. For example, if the reordering position for reph + * is post-main, it will skip above-base matras that also have a + * post-main position. + */ + if (!$skip_to_reph_move) { + /* Copied from step 2. */ + $new_reph_pos = $start + 1; + while ($new_reph_pos < $base && !self::is_halant_or_coeng($info[$new_reph_pos])) { + $new_reph_pos++; + } + + if ($new_reph_pos < $base && self::is_halant_or_coeng($info[$new_reph_pos])) { + /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */ + if ($new_reph_pos + 1 < $base && self::is_joiner($info[$new_reph_pos + 1])) { + $new_reph_pos++; + } + $skip_to_reph_move = true; + } + } + + + /* 6. Otherwise, reorder reph to the end of the syllable. + */ + if (!$skip_to_reph_move) { + $new_reph_pos = $end - 1; + while ($new_reph_pos > $start && $info[$new_reph_pos]['indic_position'] == self::POS_SMVD) { + $new_reph_pos--; + } + + /* + * If the Reph is to be ending up after a Matra,Halant sequence, + * position it before that Halant so it can interact with the Matra. + * However, if it's a plain Consonant,Halant we shouldn't do that. + * Uniscribe doesn't do this. + * TEST: U+0930,U+094D,U+0915,U+094B,U+094D + */ + //if (!$hb_options.uniscribe_bug_compatible && self::is_halant_or_coeng($info[$new_reph_pos])) { + if (self::is_halant_or_coeng($info[$new_reph_pos])) { + for ($i = $base + 1; $i < $new_reph_pos; $i++) { + if ($info[$i]['indic_category'] == self::OT_M) { + /* Ok, got it. */ + $new_reph_pos--; + } + } + } + } + + + /* Move */ + self::_move_info_pos($info, $start, $new_reph_pos + 1); + + if ($start < $base && $base <= $new_reph_pos) { + $base--; + } + } + + + /* o Reorder pre-base reordering consonants: + * + * If a pre-base reordering consonant is found, reorder it according to + * the following rules: + */ + + + if (count($GSUBdata['pref']) && $base + 1 < $end) { /* Otherwise there can't be any pre-base reordering Ra. */ + for ($i = $base + 1; $i < $end; $i++) { + if ($info[$i]['mask'] & self::FLAG(self::PREF)) { + /* 1. Only reorder a glyph produced by substitution during application + * of the <pref> feature. (Note that a font may shape a Ra consonant with + * the feature generally but block it in certain contexts.) + */ + // ??? Need to TEST if actual substitution has occurred + if ($i + 1 == $end || ($info[$i + 1]['mask'] & self::FLAG(self::PREF)) == 0) { + /* + * 2. Try to find a target position the same way as for pre-base matra. + * If it is found, reorder pre-base consonant glyph. + * + * 3. If position is not found, reorder immediately before main + * consonant. + */ + $new_pos = $base; + /* Malayalam / Tamil do not have "half" forms or explicit virama forms. + * The glyphs formed by 'half' are Chillus or ligated explicit viramas. + * We want to position matra after them. + */ + if ($scriptblock != Ucdn::SCRIPT_MALAYALAM && $scriptblock != Ucdn::SCRIPT_TAMIL) { + while ($new_pos > $start && + !(self::is_one_of($info[$new_pos - 1], self::FLAG(self::OT_M) | self::FLAG(self::OT_H) | self::FLAG(self::OT_COENG)))) { + $new_pos--; + } + + /* In Khmer coeng model, a V,Ra can go *after* matras. If it goes after a + * split matra, it should be reordered to *before* the left part of such matra. */ + if ($new_pos > $start && $info[$new_pos - 1]['indic_category'] == self::OT_M) { + $old_pos = $i; + for ($i = $base + 1; $i < $old_pos; $i++) { + if ($info[$i]['indic_category'] == self::OT_M) { + $new_pos--; + break; + } + } + } + } + + if ($new_pos > $start && self::is_halant_or_coeng($info[$new_pos - 1])) { + /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */ + if ($new_pos < $end && self::is_joiner($info[$new_pos])) { + $new_pos++; + } + } + + $old_pos = $i; + self::_move_info_pos($info, $old_pos, $new_pos); + + if ($new_pos <= $base && $base < $old_pos) { + $base++; + } + } + + break; + } + } + } + + + /* Apply 'init' to the Left Matra if it's a word start. */ + if ($info[$start]['indic_position'] == self::POS_PRE_M && + ($start == 0 || + ($info[$start - 1]['general_category'] < Ucdn::UNICODE_GENERAL_CATEGORY_FORMAT || $info[$start - 1]['general_category'] > Ucdn::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + )) { + $info[$start]['mask'] |= self::FLAG(self::INIT); + } + + + /* + * Finish off and go home! + */ + } + + public static function _move_info_pos(&$info, $from, $to) + { + $t = []; + $t[0] = $info[$from]; + if ($from > $to) { + array_splice($info, $from, 1); + array_splice($info, $to, 0, $t); + } else { + array_splice($info, $to, 0, $t); + array_splice($info, $from, 1); + } + } + + public static $ra_chars = [ + 0x0930 => 1, /* Devanagari */ + 0x09B0 => 1, /* Bengali */ + 0x09F0 => 1, /* Bengali (Assamese) */ + 0x0A30 => 1, /* Gurmukhi */ /* No Reph */ + 0x0AB0 => 1, /* Gujarati */ + 0x0B30 => 1, /* Oriya */ + 0x0BB0 => 1, /* Tamil */ /* No Reph */ + 0x0C30 => 1, /* Telugu */ /* Reph formed only with ZWJ */ + 0x0CB0 => 1, /* Kannada */ + 0x0D30 => 1, /* Malayalam */ /* No Reph, Logical Repha */ + 0x0DBB => 1, /* Sinhala */ /* Reph formed only with ZWJ */ + 0x179A => 1, /* Khmer */ /* No Reph, Visual Repha */ + ]; + + public static function is_ra($u) + { + return isset(self::$ra_chars[$u]); + } + + public static function is_one_of($info, $flags) + { + if (isset($info['is_ligature']) && $info['is_ligature']) { + return false; + } /* If it ligated, all bets are off. */ + return !!(self::FLAG($info['indic_category']) & $flags); + } + + public static function is_joiner($info) + { + return self::is_one_of($info, (self::FLAG(self::OT_ZWJ) | self::FLAG(self::OT_ZWNJ))); + } + + /* Vowels and placeholders treated as if they were consonants. */ + + public static function is_consonant($info) + { + return self::is_one_of($info, (self::FLAG(self::OT_C) | self::FLAG(self::OT_CM) | self::FLAG(self::OT_RA) | self::FLAG(self::OT_V) | self::FLAG(self::OT_NBSP) | self::FLAG(self::OT_DOTTEDCIRCLE))); + } + + public static function is_halant_or_coeng($info) + { + return self::is_one_of($info, (self::FLAG(self::OT_H) | self::FLAG(self::OT_COENG))); + } + + // From hb-private.hh + public static function in_range($u, $lo, $hi) + { + if ((($lo ^ $hi) & $lo) == 0 && (($lo ^ $hi) & $hi) == ($lo ^ $hi) && (($lo ^ $hi) & (($lo ^ $hi) + 1)) == 0) { + return ($u & ~($lo ^ $hi)) == $lo; + } else { + return $lo <= $u && $u <= $hi; + } + } + + // From hb-private.hh + public static function FLAG($x) + { + return (1 << ($x)); + } + + // BELOW from hb-ot-shape-complex-indic.cc + + /* + * Indic configurations. + */ + + // base_position + const BASE_POS_FIRST = 0; + const BASE_POS_LAST = 1; + + // reph_position + const REPH_POS_DEFAULT = 10; // POS_BEFORE_POST, + + const REPH_POS_AFTER_MAIN = 5; // POS_AFTER_MAIN, + + const REPH_POS_BEFORE_SUB = 7; // POS_BEFORE_SUB, + const REPH_POS_AFTER_SUB = 9; // POS_AFTER_SUB, + const REPH_POS_BEFORE_POST = 10; // POS_BEFORE_POST, + const REPH_POS_AFTER_POST = 12; // POS_AFTER_POST + + // reph_mode + const REPH_MODE_IMPLICIT = 0; /* Reph formed out of initial Ra,H sequence. */ + const REPH_MODE_EXPLICIT = 1; /* Reph formed out of initial Ra,H,ZWJ sequence. */ + const REPH_MODE_VIS_REPHA = 2; /* Encoded Repha character, no reordering needed. */ + const REPH_MODE_LOG_REPHA = 3; /* Encoded Repha character, needs reordering. */ + + /* + struct of indic_configs{ + KEY - script; + 0 - has_old_spec; + 1 - virama; + 2 - base_pos; + 3 - reph_pos; + 4 - reph_mode; + }; + */ + + public static $indic_configs = [/* index is SCRIPT_number from UCDN */ + 9 => [true, 0x094D, 1, 10, 0], + 10 => [true, 0x09CD, 1, 9, 0], + 11 => [true, 0x0A4D, 1, 7, 0], + 12 => [true, 0x0ACD, 1, 10, 0], + 13 => [true, 0x0B4D, 1, 5, 0], + 14 => [true, 0x0BCD, 1, 12, 0], + 15 => [true, 0x0C4D, 1, 12, 1], + 16 => [true, 0x0CCD, 1, 12, 0], + 17 => [true, 0x0D4D, 1, 5, 3], + 18 => [false, 0x0DCA, 0, 5, 1], /* Sinhala */ + 30 => [false, 0x17D2, 0, 10, 2], /* Khmer */ + 84 => [false, 0xA9C0, 1, 10, 0], /* Javanese */ + ]; + + + + /* + + // from "hb-ot-shape-complex-indic-table.cc" + + + const ISC_A = 0; // INDIC_SYLLABIC_CATEGORY_AVAGRAHA Avagraha + const ISC_Bi = 8; // INDIC_SYLLABIC_CATEGORY_BINDU Bindu + const ISC_C = 1; // INDIC_SYLLABIC_CATEGORY_CONSONANT Consonant + const ISC_CD = 1; // INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD Consonant_Dead + const ISC_CF = 17; // INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL Consonant_Final + const ISC_CHL = 1; // INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER Consonant_Head_Letter + const ISC_CM = 17; // INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL Consonant_Medial + const ISC_CP = 11; // INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER Consonant_Placeholder + const ISC_CR = 15; // INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA Consonant_Repha + const ISC_CS = 1; // INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED Consonant_Subjoined + const ISC_ML = 0; // INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER Modifying_Letter + const ISC_N = 3; // INDIC_SYLLABIC_CATEGORY_NUKTA Nukta + const ISC_x = 0; // INDIC_SYLLABIC_CATEGORY_OTHER Other + const ISC_RS = 13; // INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER Register_Shifter + const ISC_TL = 0; // INDIC_SYLLABIC_CATEGORY_TONE_LETTER Tone_Letter + const ISC_TM = 3; // INDIC_SYLLABIC_CATEGORY_TONE_MARK Tone_Mark + const ISC_V = 4; // INDIC_SYLLABIC_CATEGORY_VIRAMA Virama + const ISC_Vs = 8; // INDIC_SYLLABIC_CATEGORY_VISARGA Visarga + const ISC_Vo = 2; // INDIC_SYLLABIC_CATEGORY_VOWEL Vowel + const ISC_M = 7; // INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT Vowel_Dependent + const ISC_VI = 2; // INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT Vowel_Independent + + const IMC_B = 8; // INDIC_MATRA_CATEGORY_BOTTOM Bottom + const IMC_BR = 11; // INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT Bottom_And_Right + const IMC_I = 15; // INDIC_MATRA_CATEGORY_INVISIBLE Invisible + const IMC_L = 3; // INDIC_MATRA_CATEGORY_LEFT Left + const IMC_LR = 11; // INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT Left_And_Right + const IMC_x = 15; // INDIC_MATRA_CATEGORY_NOT_APPLICABLE Not_Applicable + const IMC_O = 5; // INDIC_MATRA_CATEGORY_OVERSTRUCK Overstruck + const IMC_R = 11; // INDIC_MATRA_CATEGORY_RIGHT Right + const IMC_T = 6; // INDIC_MATRA_CATEGORY_TOP Top + const IMC_TB = 8; // INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM Top_And_Bottom + const IMC_TBR = 11; // INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT Top_And_Bottom_And_Right + const IMC_TL = 6; // INDIC_MATRA_CATEGORY_TOP_AND_LEFT Top_And_Left + const IMC_TLR = 11; // INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT Top_And_Left_And_Right + const IMC_TR = 11; // INDIC_MATRA_CATEGORY_TOP_AND_RIGHT Top_And_Right + const IMC_VOL = 2; // INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT Visual_Order_Left + + If in original table = _(C,x), that = ISC_C,IMC_x + Value is IMC_x << 8 (or IMC_x * 256) = 3840 + plus ISC_C = 1, so = 3841 + + */ + + public static $indic_table = [ + /* Devanagari (0900..097F) */ + + /* 0900 */ 3848, 3848, 3848, 3848, 3842, 3842, 3842, 3842, + /* 0908 */ 3842, 3842, 3842, 3842, 3842, 3842, 3842, 3842, + /* 0910 */ 3842, 3842, 3842, 3842, 3842, 3841, 3841, 3841, + /* 0918 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0920 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0928 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0930 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0938 */ 3841, 3841, 1543, 2823, 3843, 3840, 2823, 775, + /* 0940 */ 2823, 2055, 2055, 2055, 2055, 1543, 1543, 1543, + /* 0948 */ 1543, 2823, 2823, 2823, 2823, 2052, 775, 2823, + /* 0950 */ 3840, 3840, 3840, 3840, 3840, 1543, 2055, 2055, + /* 0958 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0960 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0968 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0970 */ 3840, 3840, 3842, 3842, 3842, 3842, 3842, 3842, + /* 0978 */ 3840, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* Bengali (0980..09FF) */ + + /* 0980 */ 3840, 3848, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0988 */ 3842, 3842, 3842, 3842, 3842, 3840, 3840, 3842, + /* 0990 */ 3842, 3840, 3840, 3842, 3842, 3841, 3841, 3841, + /* 0998 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 09A0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 09A8 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 09B0 */ 3841, 3840, 3841, 3840, 3840, 3840, 3841, 3841, + /* 09B8 */ 3841, 3841, 3840, 3840, 3843, 3840, 2823, 775, + /* 09C0 */ 2823, 2055, 2055, 2055, 2055, 3840, 3840, 775, + /* 09C8 */ 775, 3840, 3840, 2823, 2823, 2052, 3841, 3840, + /* 09D0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 2823, + /* 09D8 */ 3840, 3840, 3840, 3840, 3841, 3841, 3840, 3841, + /* 09E0 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 09E8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 09F0 */ 3841, 3841, 3840, 3840, 3840, 3840, 3840, 3840, + /* 09F8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Gurmukhi (0A00..0A7F) */ + + /* 0A00 */ 3840, 3848, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0A08 */ 3842, 3842, 3842, 3840, 3840, 3840, 3840, 3842, + /* 0A10 */ 3842, 3840, 3840, 3842, 3842, 3841, 3841, 3841, + /* 0A18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0A20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0A28 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0A30 */ 3841, 3840, 3841, 3841, 3840, 3841, 3841, 3840, + /* 0A38 */ 3841, 3841, 3840, 3840, 3843, 3840, 2823, 775, + /* 0A40 */ 2823, 2055, 2055, 3840, 3840, 3840, 3840, 1543, + /* 0A48 */ 1543, 3840, 3840, 1543, 1543, 2052, 3840, 3840, + /* 0A50 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0A58 */ 3840, 3841, 3841, 3841, 3841, 3840, 3841, 3840, + /* 0A60 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0A68 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0A70 */ 3848, 3840, 13841, 13841, 3840, 3857, 3840, 3840, + /* 0A78 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Gujarati (0A80..0AFF) */ + + /* 0A80 */ 3840, 3848, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0A88 */ 3842, 3842, 3842, 3842, 3842, 3842, 3840, 3842, + /* 0A90 */ 3842, 3842, 3840, 3842, 3842, 3841, 3841, 3841, + /* 0A98 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0AA0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0AA8 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0AB0 */ 3841, 3840, 3841, 3841, 3840, 3841, 3841, 3841, + /* 0AB8 */ 3841, 3841, 3840, 3840, 3843, 3840, 2823, 775, + /* 0AC0 */ 2823, 2055, 2055, 2055, 2055, 1543, 3840, 1543, + /* 0AC8 */ 1543, 2823, 3840, 2823, 2823, 2052, 3840, 3840, + /* 0AD0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0AD8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0AE0 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0AE8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0AF0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0AF8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Oriya (0B00..0B7F) */ + + /* 0B00 */ 3840, 3848, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0B08 */ 3842, 3842, 3842, 3842, 3842, 3840, 3840, 3842, + /* 0B10 */ 3842, 3840, 3840, 3842, 3842, 3841, 3841, 3841, + /* 0B18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0B20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0B28 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0B30 */ 3841, 3840, 3841, 3841, 3840, 3841, 3841, 3841, + /* 0B38 */ 3841, 3841, 3840, 3840, 3843, 3840, 2823, 1543, + /* 0B40 */ 2823, 2055, 2055, 2055, 2055, 3840, 3840, 775, + /* 0B48 */ 1543, 3840, 3840, 2823, 2823, 2052, 3840, 3840, + /* 0B50 */ 3840, 3840, 3840, 3840, 3840, 3840, 1543, 2823, + /* 0B58 */ 3840, 3840, 3840, 3840, 3841, 3841, 3840, 3841, + /* 0B60 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0B68 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0B70 */ 3840, 3841, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0B78 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Tamil (0B80..0BFF) */ + + /* 0B80 */ 3840, 3840, 3848, 3840, 3840, 3842, 3842, 3842, + /* 0B88 */ 3842, 3842, 3842, 3840, 3840, 3840, 3842, 3842, + /* 0B90 */ 3842, 3840, 3842, 3842, 3842, 3841, 3840, 3840, + /* 0B98 */ 3840, 3841, 3841, 3840, 3841, 3840, 3841, 3841, + /* 0BA0 */ 3840, 3840, 3840, 3841, 3841, 3840, 3840, 3840, + /* 0BA8 */ 3841, 3841, 3841, 3840, 3840, 3840, 3841, 3841, + /* 0BB0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0BB8 */ 3841, 3841, 3840, 3840, 3840, 3840, 2823, 2823, + /* 0BC0 */ 1543, 2055, 2055, 3840, 3840, 3840, 775, 775, + /* 0BC8 */ 775, 3840, 2823, 2823, 2823, 1540, 3840, 3840, + /* 0BD0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 2823, + /* 0BD8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0BE0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0BE8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0BF0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0BF8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Telugu (0C00..0C7F) */ + + /* 0C00 */ 3840, 3848, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0C08 */ 3842, 3842, 3842, 3842, 3842, 3840, 3842, 3842, + /* 0C10 */ 3842, 3840, 3842, 3842, 3842, 3841, 3841, 3841, + /* 0C18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0C20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0C28 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0C30 */ 3841, 3841, 3841, 3841, 3840, 3841, 3841, 3841, + /* 0C38 */ 3841, 3841, 3840, 3840, 3840, 3840, 1543, 1543, + /* 0C40 */ 1543, 2823, 2823, 2823, 2823, 3840, 1543, 1543, + /* 0C48 */ 2055, 3840, 1543, 1543, 1543, 1540, 3840, 3840, + /* 0C50 */ 3840, 3840, 3840, 3840, 3840, 1543, 2055, 3840, + /* 0C58 */ 3841, 3841, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0C60 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0C68 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0C70 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0C78 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Kannada (0C80..0CFF) */ + + /* 0C80 */ 3840, 3840, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0C88 */ 3842, 3842, 3842, 3842, 3842, 3840, 3842, 3842, + /* 0C90 */ 3842, 3840, 3842, 3842, 3842, 3841, 3841, 3841, + /* 0C98 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0CA0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0CA8 */ 3841, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0CB0 */ 3841, 3841, 3841, 3841, 3840, 3841, 3841, 3841, + /* 0CB8 */ 3841, 3841, 3840, 3840, 3843, 3840, 2823, 1543, + /* 0CC0 */ 2823, 2823, 2823, 2823, 2823, 3840, 1543, 2823, + /* 0CC8 */ 2823, 3840, 2823, 2823, 1543, 1540, 3840, 3840, + /* 0CD0 */ 3840, 3840, 3840, 3840, 3840, 2823, 2823, 3840, + /* 0CD8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3841, 3840, + /* 0CE0 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0CE8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0CF0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0CF8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Malayalam (0D00..0D7F) */ + + /* 0D00 */ 3840, 3840, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0D08 */ 3842, 3842, 3842, 3842, 3842, 3840, 3842, 3842, + /* 0D10 */ 3842, 3840, 3842, 3842, 3842, 3841, 3841, 3841, + /* 0D18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0D20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0D28 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0D30 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0D38 */ 3841, 3841, 3841, 3840, 3840, 3840, 2823, 2823, + /* 0D40 */ 2823, 2823, 2823, 2055, 2055, 3840, 775, 775, + /* 0D48 */ 775, 3840, 2823, 2823, 2823, 1540, 3855, 3840, + /* 0D50 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 2823, + /* 0D58 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0D60 */ 3842, 3842, 2055, 2055, 3840, 3840, 3840, 3840, + /* 0D68 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0D70 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0D78 */ 3840, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* Sinhala (0D80..0DFF) */ + + /* 0D80 */ 3840, 3840, 3848, 3848, 3840, 3842, 3842, 3842, + /* 0D88 */ 3842, 3842, 3842, 3842, 3842, 3842, 3842, 3842, + /* 0D90 */ 3842, 3842, 3842, 3842, 3842, 3842, 3842, 3840, + /* 0D98 */ 3840, 3840, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0DA0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0DA8 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 0DB0 */ 3841, 3841, 3840, 3841, 3841, 3841, 3841, 3841, + /* 0DB8 */ 3841, 3841, 3841, 3841, 3840, 3841, 3840, 3840, + /* 0DC0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3840, + /* 0DC8 */ 3840, 3840, 1540, 3840, 3840, 3840, 3840, 2823, + /* 0DD0 */ 2823, 2823, 1543, 1543, 2055, 3840, 2055, 3840, + /* 0DD8 */ 2823, 775, 1543, 775, 2823, 2823, 2823, 2823, + /* 0DE0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0DE8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 0DF0 */ 3840, 3840, 2823, 2823, 3840, 3840, 3840, 3840, + /* 0DF8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Vedic Extensions (1CD0..1CFF) */ + + /* 1CD0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1CD8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1CE0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1CE8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1CF0 */ 3840, 3840, 3848, 3848, 3840, 3840, 3840, 3840, + /* 1CF8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + ]; + + public static $khmer_table = [ + /* Khmer (1780..17FF) */ + + /* 1780 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1788 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1790 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1798 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 17A0 */ 3841, 3841, 3841, 3842, 3842, 3842, 3842, 3842, + /* 17A8 */ 3842, 3842, 3842, 3842, 3842, 3842, 3842, 3842, + /* 17B0 */ 3842, 3842, 3842, 3842, 3840, 3840, 2823, 1543, + /* 17B8 */ 1543, 1543, 1543, 2055, 2055, 2055, 1543, 2823, + /* 17C0 */ 2823, 775, 775, 775, 2823, 2823, 3848, 3848, + /* 17C8 */ 2823, 3853, 3853, 3840, 3855, 3840, 3840, 3840, + /* 17D0 */ 3840, 1540, 3844, 3840, 3840, 3840, 3840, 3840, + /* 17D8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 17E0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 17E8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 17F0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 17F8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + ]; + + // from "hb-ot-shape-complex-indic-table.cc" + public static function indic_get_categories($u) + { + if (0x0900 <= $u && $u <= 0x0DFF) { + return self::$indic_table[$u - 0x0900 + 0]; // offset 0 for Most "indic" + } + if (0x1CD0 <= $u && $u <= 0x1D00) { + return self::$indic_table[$u - 0x1CD0 + 1152]; // offset for Vedic extensions + } + if (0x1780 <= $u && $u <= 0x17FF) { + return self::$khmer_table[$u - 0x1780]; // Khmer + } + if ($u == 0x00A0) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + if ($u == 0x25CC) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + return 3840; // (ISC_x | (IMC_x << 8)) + } + + // BELOW from hb-ot-shape-complex-indic.cc + /* + * Indic shaper. + */ + + public static function IN_HALF_BLOCK($u, $Base) + { + return (($u & ~0x7F) == $Base); + } + + public static function IS_DEVA($u) + { + return self::IN_HALF_BLOCK($u, 0x0900); + } + + public static function IS_BENG($u) + { + return self::IN_HALF_BLOCK($u, 0x0980); + } + + public static function IS_GURU($u) + { + return self::IN_HALF_BLOCK($u, 0x0A00); + } + + public static function IS_GUJR($u) + { + return self::IN_HALF_BLOCK($u, 0x0A80); + } + + public static function IS_ORYA($u) + { + return self::IN_HALF_BLOCK($u, 0x0B00); + } + + public static function IS_TAML($u) + { + return self::IN_HALF_BLOCK($u, 0x0B80); + } + + public static function IS_TELU($u) + { + return self::IN_HALF_BLOCK($u, 0x0C00); + } + + public static function IS_KNDA($u) + { + return self::IN_HALF_BLOCK($u, 0x0C80); + } + + public static function IS_MLYM($u) + { + return self::IN_HALF_BLOCK($u, 0x0D00); + } + + public static function IS_SINH($u) + { + return self::IN_HALF_BLOCK($u, 0x0D80); + } + + public static function IS_KHMR($u) + { + return self::IN_HALF_BLOCK($u, 0x1780); + } + + public static function MATRA_POS_LEFT($u) + { + return self::POS_PRE_M; + } + + public static function MATRA_POS_RIGHT($u) + { + return + (self::IS_DEVA($u) ? self::POS_AFTER_SUB : + (self::IS_BENG($u) ? self::POS_AFTER_POST : + (self::IS_GURU($u) ? self::POS_AFTER_POST : + (self::IS_GUJR($u) ? self::POS_AFTER_POST : + (self::IS_ORYA($u) ? self::POS_AFTER_POST : + (self::IS_TAML($u) ? self::POS_AFTER_POST : + (self::IS_TELU($u) ? ($u <= 0x0C42 ? self::POS_BEFORE_SUB : self::POS_AFTER_SUB) : + (self::IS_KNDA($u) ? ($u < 0x0CC3 || $u > 0xCD6 ? self::POS_BEFORE_SUB : self::POS_AFTER_SUB) : + (self::IS_MLYM($u) ? self::POS_AFTER_POST : + (self::IS_SINH($u) ? self::POS_AFTER_SUB : + (self::IS_KHMR($u) ? self::POS_AFTER_POST : + self::POS_AFTER_SUB))))))))))); /* default */ + } + + public static function MATRA_POS_TOP($u) + { + return /* BENG and MLYM don't have top matras. */ + (self::IS_DEVA($u) ? self::POS_AFTER_SUB : + (self::IS_GURU($u) ? self::POS_AFTER_POST : /* Deviate from spec */ + (self::IS_GUJR($u) ? self::POS_AFTER_SUB : + (self::IS_ORYA($u) ? self::POS_AFTER_MAIN : + (self::IS_TAML($u) ? self::POS_AFTER_SUB : + (self::IS_TELU($u) ? self::POS_BEFORE_SUB : + (self::IS_KNDA($u) ? self::POS_BEFORE_SUB : + (self::IS_SINH($u) ? self::POS_AFTER_SUB : + (self::IS_KHMR($u) ? self::POS_AFTER_POST : + self::POS_AFTER_SUB))))))))); /* default */ + } + + public static function MATRA_POS_BOTTOM($u) + { + return + (self::IS_DEVA($u) ? self::POS_AFTER_SUB : + (self::IS_BENG($u) ? self::POS_AFTER_SUB : + (self::IS_GURU($u) ? self::POS_AFTER_POST : + (self::IS_GUJR($u) ? self::POS_AFTER_POST : + (self::IS_ORYA($u) ? self::POS_AFTER_SUB : + (self::IS_TAML($u) ? self::POS_AFTER_POST : + (self::IS_TELU($u) ? self::POS_BEFORE_SUB : + (self::IS_KNDA($u) ? self::POS_BEFORE_SUB : + (self::IS_MLYM($u) ? self::POS_AFTER_POST : + (self::IS_SINH($u) ? self::POS_AFTER_SUB : + (self::IS_KHMR($u) ? self::POS_AFTER_POST : + self::POS_AFTER_SUB))))))))))); /* default */ + } + + public static function matra_position($u, $side) + { + switch ($side) { + case self::POS_PRE_C: + return self::MATRA_POS_LEFT($u); + case self::POS_POST_C: + return self::MATRA_POS_RIGHT($u); + case self::POS_ABOVE_C: + return self::MATRA_POS_TOP($u); + case self::POS_BELOW_C: + return self::MATRA_POS_BOTTOM($u); + } + return $side; + } + + // vowel matras that have to be split into two parts. + // From Harfbuzz (old) + // New HarfBuzz uses /src/hb-ucdn/ucdn.c and unicodedata_db.h for full method of decomposition for all characters + // Should always fully decompose and then recompose back, but we will just do the split matras + public static function decompose_indic($ab) + { + $sub = []; + switch ($ab) { + /* + * Decompose split matras. + */ + /* bengali */ + case 0x9cb: + $sub[0] = 0x9c7; + $sub[1] = 0x9be; + return $sub; + case 0x9cc: + $sub[0] = 0x9c7; + $sub[1] = 0x9d7; + return $sub; + /* oriya */ + case 0xb48: + $sub[0] = 0xb47; + $sub[1] = 0xb56; + return $sub; + case 0xb4b: + $sub[0] = 0xb47; + $sub[1] = 0xb3e; + return $sub; + case 0xb4c: + $sub[0] = 0xb47; + $sub[1] = 0xb57; + return $sub; + /* tamil */ + case 0xbca: + $sub[0] = 0xbc6; + $sub[1] = 0xbbe; + return $sub; + case 0xbcb: + $sub[0] = 0xbc7; + $sub[1] = 0xbbe; + return $sub; + case 0xbcc: + $sub[0] = 0xbc6; + $sub[1] = 0xbd7; + return $sub; + /* telugu */ + case 0xc48: + $sub[0] = 0xc46; + $sub[1] = 0xc56; + return $sub; + /* kannada */ + case 0xcc0: + $sub[0] = 0xcbf; + $sub[1] = 0xcd5; + return $sub; + case 0xcc7: + $sub[0] = 0xcc6; + $sub[1] = 0xcd5; + return $sub; + case 0xcc8: + $sub[0] = 0xcc6; + $sub[1] = 0xcd6; + return $sub; + case 0xcca: + $sub[0] = 0xcc6; + $sub[1] = 0xcc2; + return $sub; + case 0xccb: + $sub[0] = 0xcc6; + $sub[1] = 0xcc2; + $sub[2] = 0xcd5; + return $sub; + /* malayalam */ + case 0xd4a: + $sub[0] = 0xd46; + $sub[1] = 0xd3e; + return $sub; + case 0xd4b: + $sub[0] = 0xd47; + $sub[1] = 0xd3e; + return $sub; + case 0xd4c: + $sub[0] = 0xd46; + $sub[1] = 0xd57; + return $sub; + /* sinhala */ + // NB Some fonts break with these Sinhala decomps (although this is Uniscribe spec) + // Can check if character would be substituted by pstf and only decompose if true + // e.g. if (isset($GSUBdata['pstf'][$ab])) - would need to pass $GSUBdata as parameter to this function + case 0xdda: + $sub[0] = 0xdd9; + $sub[1] = 0xdca; + return $sub; + case 0xddc: + $sub[0] = 0xdd9; + $sub[1] = 0xdcf; + return $sub; + case 0xddd: + $sub[0] = 0xdd9; + $sub[1] = 0xdcf; + $sub[2] = 0xdca; + return $sub; + case 0xdde: + $sub[0] = 0xdd9; + $sub[1] = 0xddf; + return $sub; + /* khmer */ + case 0x17be: + $sub[0] = 0x17c1; + $sub[1] = 0x17be; + return $sub; + case 0x17bf: + $sub[0] = 0x17c1; + $sub[1] = 0x17bf; + return $sub; + case 0x17c0: + $sub[0] = 0x17c1; + $sub[1] = 0x17c0; + return $sub; + + case 0x17c4: + $sub[0] = 0x17c1; + $sub[1] = 0x17c4; + return $sub; + case 0x17c5: + $sub[0] = 0x17c1; + $sub[1] = 0x17c5; + return $sub; + /* tibetan - included here although does not use Inidc shaper in other ways */ + case 0xf73: + $sub[0] = 0xf71; + $sub[1] = 0xf72; + return $sub; + case 0xf75: + $sub[0] = 0xf71; + $sub[1] = 0xf74; + return $sub; + case 0xf76: + $sub[0] = 0xfb2; + $sub[1] = 0xf80; + return $sub; + case 0xf77: + $sub[0] = 0xfb2; + $sub[1] = 0xf81; + return $sub; + case 0xf78: + $sub[0] = 0xfb3; + $sub[1] = 0xf80; + return $sub; + case 0xf79: + $sub[0] = 0xfb3; + $sub[1] = 0xf71; + $sub[2] = 0xf80; + return $sub; + case 0xf81: + $sub[0] = 0xf71; + $sub[1] = 0xf80; + return $sub; + } + return false; + } + + public static function bubble_sort(&$arr, $start, $len) + { + if ($len < 2) { + return; + } + $k = $start + $len - 2; + while ($k >= $start) { + for ($j = $start; $j <= $k; $j++) { + if ($arr[$j]['indic_position'] > $arr[$j + 1]['indic_position']) { + $t = $arr[$j]; + $arr[$j] = $arr[$j + 1]; + $arr[$j + 1] = $t; + } + } + $k--; + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Shaper/Myanmar.php b/src/vendor/mpdf/mpdf/src/Shaper/Myanmar.php new file mode 100644 index 000000000..9a68edacf --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Shaper/Myanmar.php @@ -0,0 +1,543 @@ +<?php + +namespace Mpdf\Shaper; + +class Myanmar +{ + /* FROM hb-ot-shape-complex-indic-private.hh */ + + // indic_category + const OT_X = 0; + const OT_C = 1; + const OT_V = 2; + const OT_N = 3; + const OT_H = 4; + const OT_ZWNJ = 5; + const OT_ZWJ = 6; + const OT_M = 7; /* Matra or Dependent Vowel */ + const OT_SM = 8; + const OT_VD = 9; + const OT_A = 10; + const OT_NBSP = 11; + const OT_DOTTEDCIRCLE = 12; /* Not in the spec, but special in Uniscribe. /Very very/ special! */ + const OT_RS = 13; /* Register Shifter, used in Khmer OT spec */ + const OT_COENG = 14; + const OT_REPHA = 15; + const OT_RA = 16; /* Not explicitly listed in the OT spec, but used in the grammar. */ + const OT_CM = 17; + + /* FROM hb-ot-shape-complex-myanmar.hh */ + + // myanmar_category + const OT_DB = 3; // same as Indic::OT_N; /* Dot below */ + const OT_GB = 12; // same as Indic::OT_DOTTEDCIRCLE; + const OT_AS = 18; /* Asat */ + const OT_D = 19; /* Digits except zero */ + const OT_D0 = 20; /* Digit zero */ + const OT_MH = 21; /* Various consonant medial types */ + const OT_MR = 22; /* Various consonant medial types */ + const OT_MW = 23; /* Various consonant medial types */ + const OT_MY = 24; /* Various consonant medial types */ + const OT_PT = 25; /* Pwo and other tones */ + + const OT_VABV = 26; + const OT_VBLW = 27; + const OT_VPRE = 28; + const OT_VPST = 29; + const OT_VS = 30; /* Variation selectors */ + + /* Visual positions in a syllable from left to right. */ + /* FROM hb-ot-shape-complex-myanmar-private.hh */ + + // myanmar_position + const POS_START = 0; + + const POS_RA_TO_BECOME_REPH = 1; + const POS_PRE_M = 2; + const POS_PRE_C = 3; + + const POS_BASE_C = 4; + const POS_AFTER_MAIN = 5; + + const POS_ABOVE_C = 6; + + const POS_BEFORE_SUB = 7; + const POS_BELOW_C = 8; + const POS_AFTER_SUB = 9; + + const POS_BEFORE_POST = 10; + const POS_POST_C = 11; + const POS_AFTER_POST = 12; + + const POS_FINAL_C = 13; + const POS_SMVD = 14; + + const POS_END = 15; + + // Based on myanmar_category used to make string to find syllables + // OT_ to string character (using e.g. OT_C from MYANMAR) hb-ot-shape-complex-myanmar-private.hh + public static $myanmar_category_char = [ + 'x', + 'C', + 'V', + 'N', + 'H', + 'Z', + 'J', + 'x', + 'S', + 'x', + 'A', + 'x', + 'D', + 'x', + 'x', + 'x', + 'R', + 'x', + 'a', /* As Asat */ + 'd', /* Digits except zero */ + 'o', /* Digit zero */ + 'k', /* Medial types */ + 'l', /* Medial types */ + 'm', /* Medial types */ + 'n', /* Medial types */ + 'p', /* Pwo and other tones */ + 'v', /* Vowel aboVe */ + 'b', /* Vowel Below */ + 'e', /* Vowel prE */ + 't', /* Vowel posT */ + 's', /* variation Selector */ + ]; + + public static function set_myanmar_properties(&$info) + { + $u = $info['uni']; + $type = self::myanmar_get_categories($u); + $cat = ($type & 0x7F); + $pos = ($type >> 8); + /* + * Re-assign category + * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze + */ + if (self::in_range($u, 0xFE00, 0xFE0F)) { + $cat = self::OT_VS; + } elseif ($u == 0x200C) { + $cat = self::OT_ZWNJ; + } elseif ($u == 0x200D) { + $cat = self::OT_ZWJ; + } + + switch ($u) { + case 0x002D: + case 0x00A0: + case 0x00D7: + case 0x2012: + case 0x2013: + case 0x2014: + case 0x2015: + case 0x2022: + case 0x25CC: + case 0x25FB: + case 0x25FC: + case 0x25FD: + case 0x25FE: + $cat = self::OT_GB; + break; + + case 0x1004: + case 0x101B: + case 0x105A: + $cat = self::OT_RA; + break; + + case 0x1032: + case 0x1036: + $cat = self::OT_A; + break; + + case 0x103A: + $cat = self::OT_AS; + break; + + case 0x1041: + case 0x1042: + case 0x1043: + case 0x1044: + case 0x1045: + case 0x1046: + case 0x1047: + case 0x1048: + case 0x1049: + case 0x1090: + case 0x1091: + case 0x1092: + case 0x1093: + case 0x1094: + case 0x1095: + case 0x1096: + case 0x1097: + case 0x1098: + case 0x1099: + $cat = self::OT_D; + break; + + case 0x1040: + $cat = self::OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */ + break; + + case 0x103E: + case 0x1060: + $cat = self::OT_MH; + break; + + case 0x103C: + $cat = self::OT_MR; + break; + + case 0x103D: + case 0x1082: + $cat = self::OT_MW; + break; + + case 0x103B: + case 0x105E: + case 0x105F: + $cat = self::OT_MY; + break; + + case 0x1063: + case 0x1064: + case 0x1069: + case 0x106A: + case 0x106B: + case 0x106C: + case 0x106D: + case 0xAA7B: + $cat = self::OT_PT; + break; + + case 0x1038: + case 0x1087: + case 0x1088: + case 0x1089: + case 0x108A: + case 0x108B: + case 0x108C: + case 0x108D: + case 0x108F: + case 0x109A: + case 0x109B: + case 0x109C: + $cat = self::OT_SM; + break; + } + + if ($cat == self::OT_M) { + switch ($pos) { + case self::POS_PRE_C: + $cat = self::OT_VPRE; + $pos = self::POS_PRE_M; + break; + case self::POS_ABOVE_C: + $cat = self::OT_VABV; + break; + case self::POS_BELOW_C: + $cat = self::OT_VBLW; + break; + case self::POS_POST_C: + $cat = self::OT_VPST; + break; + } + } + $info['myanmar_category'] = $cat; + $info['myanmar_position'] = $pos; + } + + // syllable_type + const CONSONANT_SYLLABLE = 0; + const BROKEN_CLUSTER = 3; + const NON_MYANMAR_CLUSTER = 4; + + public static function set_syllables(&$o, $s, &$broken_syllables) + { + $ptr = 0; + $syllable_serial = 1; + $broken_syllables = false; + + while ($ptr < strlen($s)) { + $match = ''; + $syllable_length = 1; + $syllable_type = self::NON_MYANMAR_CLUSTER; + // CONSONANT_SYLLABLE Consonant syllable + // From OT spec: + if (preg_match('/^(RaH)?([C|R]|V|d|D)[s]?(H([C|R|V])[s]?)*(H|[a]*[n]?[l]?((m[k]?|k)[a]?)?[e]*[v]*[b]*[A]*(N[a]?)?(t[k]?[a]*[v]*[A]*(N[a]?)?)*(p[A]*(N[a]?)?)*S*[J|Z]?)/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::CONSONANT_SYLLABLE; + } // BROKEN_CLUSTER syllable + elseif (preg_match('/^(RaH)?s?(H|[a]*[n]?[l]?((m[k]?|k)[a]?)?[e]*[v]*[b]*[A]*(N[a]?)?(t[k]?[a]*[v]*[A]*(N[a]?)?)*(p[A]*(N[a]?)?)*S*[J|Z]?)/', substr($s, $ptr), $ma)) { + if (strlen($ma[0])) { // May match blank + $syllable_length = strlen($ma[0]); + $syllable_type = self::BROKEN_CLUSTER; + $broken_syllables = true; + } + } + for ($i = $ptr; $i < $ptr + $syllable_length; $i++) { + $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type; + } + $ptr += $syllable_length; + $syllable_serial++; + if ($syllable_serial == 16) { + $syllable_serial = 1; + } + } + } + + public static function reordering(&$info, $GSUBdata, $broken_syllables, $dottedcircle) + { + if ($broken_syllables && $dottedcircle) { + self::insert_dotted_circles($info, $dottedcircle); + } + $count = count($info); + if (!$count) { + return; + } + $last = 0; + $last_syllable = $info[0]['syllable']; + for ($i = 1; $i < $count; $i++) { + if ($last_syllable != $info[$i]['syllable']) { + self::reordering_syllable($info, $GSUBdata, $last, $i); + $last = $i; + $last_syllable = $info[$last]['syllable']; + } + } + self::reordering_syllable($info, $GSUBdata, $last, $count); + } + + public static function insert_dotted_circles(&$info, $dottedcircle) + { + $idx = 0; + $last_syllable = 0; + while ($idx < count($info)) { + $syllable = $info[$idx]['syllable']; + $syllable_type = ($syllable & 0x0F); + if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) { + $last_syllable = $syllable; + $dottedcircle[0]['syllable'] = $info[$idx]['syllable']; + array_splice($info, $idx, 0, $dottedcircle); + } else { + $idx++; + } + } + // In case of final bloken cluster... + $syllable = $info[$idx]['syllable']; + $syllable_type = ($syllable & 0x0F); + if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) { + $dottedcircle[0]['syllable'] = $info[$idx]['syllable']; + array_splice($info, $idx, 0, $dottedcircle); + } + } + + /* Rules from: + * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */ + + public static function reordering_syllable(&$info, $GSUBdata, $start, $end) + { + /* vowel_syllable: We made the vowels look like consonants. So uses the consonant logic! */ + /* broken_cluster: We already inserted dotted-circles, so just call the standalone_cluster. */ + + $syllable_type = ($info[$start]['syllable'] & 0x0F); + if ($syllable_type == self::NON_MYANMAR_CLUSTER) { + return; + } + if ($syllable_type == self::BROKEN_CLUSTER) { + //if ($uniscribe_bug_compatible) { + /* For dotted-circle, this is what Uniscribe does: + * If dotted-circle is the last glyph, it just does nothing. + * i.e. It doesn't form Reph. */ + if ($info[$end - 1]['myanmar_category'] == self::OT_DOTTEDCIRCLE) { + return; + } + } + + $base = $end; + $has_reph = false; + $limit = $start; + + if (($start + 3 <= $end) && + $info[$start]['myanmar_category'] == self::OT_RA && + $info[$start + 1]['myanmar_category'] == self::OT_AS && + $info[$start + 2]['myanmar_category'] == self::OT_H) { + $limit += 3; + $base = $start; + $has_reph = true; + } + + if (!$has_reph) { + $base = $limit; + } + + for ($i = $limit; $i < $end; $i++) { + if (self::is_consonant($info[$i])) { + $base = $i; + break; + } + } + + + /* Reorder! */ + $i = $start; + for (; $i < $start + ($has_reph ? 3 : 0); $i++) { + $info[$i]['myanmar_position'] = self::POS_AFTER_MAIN; + } + for (; $i < $base; $i++) { + $info[$i]['myanmar_position'] = self::POS_PRE_C; + } + if ($i < $end) { + $info[$i]['myanmar_position'] = self::POS_BASE_C; + $i++; + } + $pos = self::POS_AFTER_MAIN; + /* The following loop may be ugly, but it implements all of + * Myanmar reordering! */ + for (; $i < $end; $i++) { + if ($info[$i]['myanmar_category'] == self::OT_MR) { /* Pre-base reordering */ + $info[$i]['myanmar_position'] = self::POS_PRE_C; + continue; + } + if ($info[$i]['myanmar_position'] < self::POS_BASE_C) { /* Left matra */ + continue; + } + + if ($pos == self::POS_AFTER_MAIN && $info[$i]['myanmar_category'] == self::OT_VBLW) { + $pos = self::POS_BELOW_C; + $info[$i]['myanmar_position'] = $pos; + continue; + } + + if ($pos == self::POS_BELOW_C && $info[$i]['myanmar_category'] == self::OT_A) { + $info[$i]['myanmar_position'] = self::POS_BEFORE_SUB; + continue; + } + if ($pos == self::POS_BELOW_C && $info[$i]['myanmar_category'] == self::OT_VBLW) { + $info[$i]['myanmar_position'] = $pos; + continue; + } + if ($pos == self::POS_BELOW_C && $info[$i]['myanmar_category'] != self::OT_A) { + $pos = self::POS_AFTER_SUB; + $info[$i]['myanmar_position'] = $pos; + continue; + } + $info[$i]['myanmar_position'] = $pos; + } + + + /* Sit tight, rock 'n roll! */ + self::bubble_sort($info, $start, $end - $start); + } + + public static function is_one_of($info, $flags) + { + if (isset($info['is_ligature']) && $info['is_ligature']) { + return false; + } /* If it ligated, all bets are off. */ + return !!(self::FLAG($info['myanmar_category']) & $flags); + } + + /* Vowels and placeholders treated as if they were consonants. */ + + public static function is_consonant($info) + { + return self::is_one_of($info, (self::FLAG(self::OT_C) | self::FLAG(self::OT_CM) | self::FLAG(self::OT_RA) | self::FLAG(self::OT_V) | self::FLAG(self::OT_NBSP) | self::FLAG(self::OT_GB))); + } + +// From hb-private.hh + public static function in_range($u, $lo, $hi) + { + if ((($lo ^ $hi) & $lo) == 0 && (($lo ^ $hi) & $hi) == ($lo ^ $hi) && (($lo ^ $hi) & (($lo ^ $hi) + 1)) == 0) { + return ($u & ~($lo ^ $hi)) == $lo; + } else { + return $lo <= $u && $u <= $hi; + } + } + + // From hb-private.hh + public static function FLAG($x) + { + return (1 << ($x)); + } + + public static function FLAG_RANGE($x, $y) + { + return self::FLAG($y + 1) - self::FLAG($x); + } + + // BELOW from hb-ot-shape-complex-indic.cc + // see INDIC for details + public static $myanmar_table = [ + /* Myanmar (1000..109F) */ + + /* 1000 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1008 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1010 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1018 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1020 */ 3841, 3842, 3842, 3842, 3842, 3842, 3842, 3842, + /* 1028 */ 3842, 3842, 3842, 2823, 2823, 1543, 1543, 2055, + /* 1030 */ 2055, 775, 1543, 1543, 1543, 1543, 3848, 3843, + /* 1038 */ 3848, 3844, 1540, 3857, 3857, 3857, 3857, 3841, + /* 1040 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1048 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1050 */ 3841, 3841, 3842, 3842, 3842, 3842, 2823, 2823, + /* 1058 */ 2055, 2055, 3841, 3841, 3841, 3841, 3857, 3857, + /* 1060 */ 3857, 3841, 2823, 3843, 3843, 3841, 3841, 2823, + /* 1068 */ 2823, 3843, 3843, 3843, 3843, 3843, 3841, 3841, + /* 1070 */ 3841, 1543, 1543, 1543, 1543, 3841, 3841, 3841, + /* 1078 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1080 */ 3841, 3841, 3857, 2823, 775, 1543, 1543, 3843, + /* 1088 */ 3843, 3843, 3843, 3843, 3843, 3843, 3841, 3843, + /* 1090 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1098 */ 3840, 3840, 3843, 3843, 2823, 1543, 3840, 3840, + /* Myanmar Extended-A (AA60..AA7F) */ + + /* AA60 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA68 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA70 */ 3840, 3841, 3841, 3841, 3840, 3840, 3840, 3840, + /* AA78 */ 3840, 3840, 3841, 3843, 3840, 3840, 3840, 3840, + ]; + + // from "hb-ot-shape-complex-indic-table.cc" + public static function myanmar_get_categories($u) + { + if (0x1000 <= $u && $u <= 0x109F) { + return self::$myanmar_table[$u - 0x1000 + 0]; // offset 0 for Most "myanmar" + } + if (0xAA60 <= $u && $u <= 0xAA7F) { + return self::$myanmar_table[$u - 0xAA60 + 160]; // offset for extensions + } + if ($u == 0x00A0) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + if ($u == 0x25CC) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + return 3840; // (ISC_x | (IMC_x << 8)) + } + + public static function bubble_sort(&$arr, $start, $len) + { + if ($len < 2) { + return; + } + $k = $start + $len - 2; + while ($k >= $start) { + for ($j = $start; $j <= $k; $j++) { + if ($arr[$j]['myanmar_position'] > $arr[$j + 1]['myanmar_position']) { + $t = $arr[$j]; + $arr[$j] = $arr[$j + 1]; + $arr[$j + 1] = $t; + } + } + $k--; + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Shaper/Sea.php b/src/vendor/mpdf/mpdf/src/Shaper/Sea.php new file mode 100644 index 000000000..40adaccfa --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Shaper/Sea.php @@ -0,0 +1,397 @@ +<?php + +namespace Mpdf\Shaper; + +class Sea +{ + // South East Asian shaper + // sea_category + const OT_X = 0; + + const OT_C = 1; + + const OT_IV = 2; # Independent Vowel + + const OT_T = 3; # Tone Marks + + const OT_H = 4; # Halant + + const OT_A = 10; # Anusvara + + const OT_GB = 12; # Generic Base (OT_DOTTEDCIRCLE in Indic) + + const OT_CM = 17; # Consonant Medial + + const OT_MR = 22; # Medial Ra + + const OT_VABV = 26; + + const OT_VBLW = 27; + + const OT_VPRE = 28; + + const OT_VPST = 29; + + // ? From Indic categories + const OT_ZWNJ = 5; + + const OT_ZWJ = 6; + + const OT_M = 7; + + const OT_SM = 8; + + const OT_VD = 9; + + const OT_NBSP = 11; + + const OT_RS = 13; + + const OT_COENG = 14; + + const OT_REPHA = 15; + + const OT_RA = 16; + + /* Visual positions in a syllable from left to right. */ + // sea_position + const POS_START = 0; + + const POS_RA_TO_BECOME_REPH = 1; + + const POS_PRE_M = 2; + + const POS_PRE_C = 3; + + const POS_BASE_C = 4; + + const POS_AFTER_MAIN = 5; + + const POS_ABOVE_C = 6; + + const POS_BEFORE_SUB = 7; + + const POS_BELOW_C = 8; + + const POS_AFTER_SUB = 9; + + const POS_BEFORE_POST = 10; + + const POS_POST_C = 11; + + const POS_AFTER_POST = 12; + + const POS_FINAL_C = 13; + + const POS_SMVD = 14; + + const POS_END = 15; + + // Based on sea_category used to make string to find syllables + // OT_ to string character (using e.g. OT_C from INDIC) hb-ot-shape-complex-sea-private.hh + public static $sea_category_char = [ + 'x', + 'C', + 'V', + 'T', + 'H', + 'x', + 'x', + 'x', + 'x', + 'x', + 'A', + 'x', + 'G', + 'x', + 'x', + 'x', + 'x', + 'M', + 'x', + 'x', + 'x', + 'x', + 'R', + 'x', + 'x', + 'x', + 'a', + 'b', + 'p', + 't', + ]; + + public static function set_sea_properties(&$info, $scriptblock) + { + $u = $info['uni']; + $type = self::sea_get_categories($u); + $cat = ($type & 0x7F); + $pos = ($type >> 8); + + /* + * Re-assign category + */ + // Medial Ra + if ($u == 0x1A55 || $u == 0xAA34) { + $cat = self::OT_MR; + } + + /* + * Re-assign position. + */ + if ($cat == self::OT_M) { // definitely "OT_M" in HarfBuzz - although this does not seem to have been defined ? should be OT_MR + switch ($pos) { + case self::POS_PRE_C: + $cat = self::OT_VPRE; + break; + case self::POS_ABOVE_C: + $cat = self::OT_VABV; + break; + case self::POS_BELOW_C: + $cat = self::OT_VBLW; + break; + case self::POS_POST_C: + $cat = self::OT_VPST; + break; + } + } + + $info['sea_category'] = $cat; + $info['sea_position'] = $pos; + } + + // syllable_type + const CONSONANT_SYLLABLE = 0; + + const BROKEN_CLUSTER = 1; + + const NON_SEA_CLUSTER = 2; + + public static function set_syllables(&$o, $s, &$broken_syllables) + { + $ptr = 0; + $syllable_serial = 1; + $broken_syllables = false; + while ($ptr < strlen($s)) { + $match = ''; + $syllable_length = 1; + $syllable_type = self::NON_SEA_CLUSTER; + + // CONSONANT_SYLLABLE Consonant syllable + if (preg_match('/^(C|V|G)(p|a|b|t|HC|M|R|T|A)*/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::CONSONANT_SYLLABLE; + } // BROKEN_CLUSTER syllable + elseif (preg_match('/^(p|a|b|t|HC|M|R|T|A)+/', substr($s, $ptr), $ma)) { + $syllable_length = strlen($ma[0]); + $syllable_type = self::BROKEN_CLUSTER; + $broken_syllables = true; + } + + for ($i = $ptr; $i < $ptr + $syllable_length; $i++) { + $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type; + } + $ptr += $syllable_length; + $syllable_serial++; + if ($syllable_serial == 16) { + $syllable_serial = 1; + } + } + } + + public static function initial_reordering(&$info, $GSUBdata, $broken_syllables, $scriptblock, $dottedcircle) + { + + if ($broken_syllables && $dottedcircle) { + self::insert_dotted_circles($info, $dottedcircle); + } + + $count = count($info); + if (!$count) { + return; + } + $last = 0; + $last_syllable = $info[0]['syllable']; + for ($i = 1; $i < $count; $i++) { + if ($last_syllable != $info[$i]['syllable']) { + self::initial_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $i); + $last = $i; + $last_syllable = $info[$last]['syllable']; + } + } + self::initial_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $count); + } + + public static function insert_dotted_circles(&$info, $dottedcircle) + { + $idx = 0; + $last_syllable = 0; + while ($idx < count($info)) { + $syllable = $info[$idx]['syllable']; + $syllable_type = ($syllable & 0x0F); + if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) { + $last_syllable = $syllable; + $dottedcircle[0]['syllable'] = $info[$idx]['syllable']; + array_splice($info, $idx, 0, $dottedcircle); + } else { + $idx++; + } + } + } + + public static function initial_reordering_syllable(&$info, $GSUBdata, $scriptblock, $start, $end) + { + /* broken_cluster: We already inserted dotted-circles, so just call the standalone_cluster. */ + + $syllable_type = ($info[$start]['syllable'] & 0x0F); + if ($syllable_type == self::NON_SEA_CLUSTER) { + return; + } + if ($syllable_type == self::BROKEN_CLUSTER) { + /* For dotted-circle, this is what Uniscribe does: + * If dotted-circle is the last glyph, it just does nothing. */ + if ($info[$end - 1]['sea_category'] == self::OT_GB) { + return; + } + } + + $base = $start; + $i = $start; + for (; $i < $base; $i++) { + $info[$i]['sea_position'] = self::POS_PRE_C; + } + if ($i < $end) { + $info[$i]['sea_position'] = self::POS_BASE_C; + $i++; + } + for (; $i < $end; $i++) { + if (isset($info[$i]['sea_category']) && $info[$i]['sea_category'] == self::OT_MR) { /* Pre-base reordering */ + $info[$i]['sea_position'] = self::POS_PRE_C; + continue; + } + if (isset($info[$i]['sea_category']) && $info[$i]['sea_category'] == self::OT_VPRE) { /* Left matra */ + $info[$i]['sea_position'] = self::POS_PRE_M; + continue; + } + $info[$i]['sea_position'] = self::POS_AFTER_MAIN; + } + + /* Sit tight, rock 'n roll! */ + self::bubble_sort($info, $start, $end - $start); + } + + public static function final_reordering(&$info, $GSUBdata, $scriptblock) + { + $count = count($info); + if (!$count) { + return; + } + $last = 0; + $last_syllable = $info[0]['syllable']; + for ($i = 1; $i < $count; $i++) { + if ($last_syllable != $info[$i]['syllable']) { + self::final_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $i); + $last = $i; + $last_syllable = $info[$last]['syllable']; + } + } + self::final_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $count); + } + + public static function final_reordering_syllable(&$info, $GSUBdata, $scriptblock, $start, $end) + { + /* + * Nothing to do here at present! + */ + } + + public static $sea_table = [ + /* New Tai Lue (1980..19DF) */ + + /* 1980 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1988 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1990 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1998 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 19A0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 19A8 */ 3841, 3841, 3841, 3841, 3840, 3840, 3840, 3840, + /* 19B0 */ 2823, 2823, 2823, 2823, 2823, 775, 775, 775, + /* 19B8 */ 2823, 2823, 775, 2823, 2823, 2823, 2823, 2823, + /* 19C0 */ 2823, 3857, 3857, 3857, 3857, 3857, 3857, 3857, + /* 19C8 */ 3843, 3843, 3840, 3840, 3840, 3840, 3840, 3840, + /* 19D0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 19D8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Tai Tham (1A20..1AAF) */ + + /* 1A20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1A28 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1A30 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1A38 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1A40 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* 1A48 */ 3841, 3841, 3841, 3841, 3841, 3842, 3842, 3842, + /* 1A50 */ 3842, 3842, 3842, 3841, 3841, 3857, 3857, 3857, + /* 1A58 */ 3857, 3857, 3857, 3857, 3857, 3857, 3857, 3840, + /* 1A60 */ 3844, 2823, 1543, 2823, 2823, 1543, 1543, 1543, + /* 1A68 */ 1543, 2055, 2055, 1543, 2055, 2823, 775, 775, + /* 1A70 */ 775, 775, 775, 1543, 1543, 3843, 3843, 3843, + /* 1A78 */ 3843, 3843, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1A80 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1A88 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1A90 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1A98 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1AA0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* 1AA8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* Cham (AA00..AA5F) */ + + /* AA00 */ 3842, 3842, 3842, 3842, 3842, 3842, 3841, 3841, + /* AA08 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA10 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841, + /* AA28 */ 3841, 1543, 1543, 1543, 1543, 2055, 1543, 775, + /* AA30 */ 775, 1543, 2055, 3857, 3857, 3857, 3857, 3840, + /* AA38 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* AA40 */ 3857, 3857, 3857, 3857, 3857, 3857, 3857, 3857, + /* AA48 */ 3857, 3857, 3857, 3857, 3857, 3857, 3840, 3840, + /* AA50 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + /* AA58 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, + ]; + + public static function sea_get_categories($u) + { + if (0x1980 <= $u && $u <= 0x19DF) { + return self::$sea_table[$u - 0x1980]; // offset 0 for New Tai Lue + } + if (0x1A20 <= $u && $u <= 0x1AAF) { + return self::$sea_table[$u - 0x1A20 + 96]; // offset for Tai Tham + } + if (0xAA00 <= $u && $u <= 0xAA5F) { + return self::$sea_table[$u - 0xAA00 + 96 + 144]; // Cham + } + if ($u == 0x00A0) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + if ($u == 0x25CC) { + return 3851; // (ISC_CP | (IMC_x << 8)) + } + return 3840; // (ISC_x | (IMC_x << 8)) + } + + public static function bubble_sort(&$arr, $start, $len) + { + if ($len < 2) { + return; + } + $k = $start + $len - 2; + while ($k >= $start) { + for ($j = $start; $j <= $k; $j++) { + if ($arr[$j]['sea_position'] > $arr[$j + 1]['sea_position']) { + $t = $arr[$j]; + $arr[$j] = $arr[$j + 1]; + $arr[$j + 1] = $t; + } + } + $k--; + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/SizeConverter.php b/src/vendor/mpdf/mpdf/src/SizeConverter.php new file mode 100644 index 000000000..111754466 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/SizeConverter.php @@ -0,0 +1,154 @@ +<?php + +namespace Mpdf; + +use Psr\Log\LoggerInterface; +use Mpdf\Log\Context as LogContext; +use Mpdf\PsrLogAwareTrait\PsrLogAwareTrait; + +class SizeConverter implements \Psr\Log\LoggerAwareInterface +{ + + use PsrLogAwareTrait; + + private $dpi; + + private $defaultFontSize; + + /** + * @var \Mpdf\Mpdf + */ + private $mpdf; + + public function __construct($dpi, $defaultFontSize, Mpdf $mpdf, LoggerInterface $logger) + { + $this->dpi = $dpi; + $this->defaultFontSize = $defaultFontSize; + $this->mpdf = $mpdf; + $this->logger = $logger; + } + + /** + * Depends of maxsize value to make % work properly. Usually maxsize == pagewidth + * For text $maxsize = $fontsize + * Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize + * + * @param mixed $size + * @param mixed $maxsize + * @param mixed $fontsize + * @param mixed $usefontsize Set false for e.g. margins - will ignore fontsize for % values + * + * @return float Final size in mm + */ + public function convert($size = 5, $maxsize = 0, $fontsize = false, $usefontsize = true) + { + $size = trim(strtolower($size)); + $res = preg_match('/^(?P<size>[-0-9.,]+([eE]\-?[0-9]+)?)?(?P<unit>[%a-z-]+)?$/', $size, $parts); + if (!$res) { + // ignore definition + $this->logger->warning(sprintf('Invalid size representation "%s"', $size), ['context' => LogContext::CSS_SIZE_CONVERSION]); + } + + $unit = !empty($parts['unit']) ? $parts['unit'] : null; + $size = !empty($parts['size']) ? (float) $parts['size'] : 0.0; + + switch ($unit) { + case 'mm': + // do nothing + break; + + case 'cm': + $size *= 10; + break; + + case 'pt': + $size *= 1 / Mpdf::SCALE; + break; + + case 'rem': + $size *= $this->mpdf->default_font_size / Mpdf::SCALE; + break; + + case '%': + if ($fontsize && $usefontsize) { + $size *= $fontsize / 100; + } else { + $size *= $maxsize / 100; + } + break; + + case 'in': + // mm in an inch + $size *= 25.4; + break; + + case 'pc': + // PostScript picas + $size *= 38.1 / 9; + break; + + case 'ex': + // Approximates "ex" as half of font height + $size *= $this->multiplyFontSize($fontsize, $maxsize, 0.5); + break; + + case 'em': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 1); + break; + + case 'thin': + $size = 1 * (25.4 / $this->dpi); + break; + + case 'medium': + $size = 3 * (25.4 / $this->dpi); + // Commented-out dead code from legacy method + // $size *= $this->multiplyFontSize($fontsize, $maxsize, 1); + break; + + case 'thick': + $size = 5 * (25.4 / $this->dpi); // 5 pixel width for table borders + break; + + case 'xx-small': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 0.7); + break; + + case 'x-small': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 0.77); + break; + + case 'small': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 0.86); + break; + + case 'large': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 1.2); + break; + + case 'x-large': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 1.5); + break; + + case 'xx-large': + $size *= $this->multiplyFontSize($fontsize, $maxsize, 2); + break; + + case 'px': + default: + $size *= (25.4 / $this->dpi); + break; + } + + return $size; + } + + private function multiplyFontSize($fontsize, $maxsize, $ratio) + { + if ($fontsize) { + return $fontsize * $ratio; + } + + return $maxsize * $ratio; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Strict.php b/src/vendor/mpdf/mpdf/src/Strict.php new file mode 100644 index 000000000..bab863db7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Strict.php @@ -0,0 +1,67 @@ +<?php + +namespace Mpdf; + +trait Strict +{ + + /** + * @param string $name method name + * @param array $args arguments + */ + public function __call($name, $args) + { + $class = method_exists($this, $name) ? 'parent' : get_class($this); + throw new \Mpdf\MpdfException("Call to undefined method $class::$name()"); + } + + /** + * @param string $name lowercase method name + * @param array $args arguments + */ + public static function __callStatic($name, $args) + { + $class = get_called_class(); + throw new \Mpdf\MpdfException("Call to undefined static function $class::$name()"); + } + + /** + * @param string $name property name + */ + public function &__get($name) + { + $class = get_class($this); + throw new \Mpdf\MpdfException("Cannot read an undeclared property $class::\$$name"); + } + + /** + * @param string $name property name + * @param mixed $value property value + */ + public function __set($name, $value) + { + $class = get_class($this); + throw new \Mpdf\MpdfException("Cannot write to an undeclared property $class::\$$name"); + } + + /** + * @param string $name property name + * @throws \Kdyby\StrictObjects\\Mpdf\MpdfException + */ + public function __isset($name) + { + $class = get_class($this); + throw new \Mpdf\MpdfException("Cannot read an undeclared property $class::\$$name"); + } + + /** + * @param string $name property name + * @throws \Kdyby\StrictObjects\\Mpdf\MpdfException + */ + public function __unset($name) + { + $class = get_class($this); + throw new \Mpdf\MpdfException("Cannot unset the property $class::\$$name."); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/TTFontFile.php b/src/vendor/mpdf/mpdf/src/TTFontFile.php new file mode 100644 index 000000000..2591bdbb9 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/TTFontFile.php @@ -0,0 +1,4960 @@ +<?php + +namespace Mpdf; + +use Mpdf\Fonts\FontCache; +use Mpdf\Fonts\GlyphOperator; + +// NOTE*** If you change the defined constants below, be sure to delete all temporary font data files in /ttfontdata/ +// to force mPDF to regenerate cached font files. +if (!defined('_OTL_OLD_SPEC_COMPAT_2')) { + define('_OTL_OLD_SPEC_COMPAT_2', true); +} + +// Define the value used in the "head" table of a created TTF file +// 0x74727565 "true" for Mac +// 0x00010000 for Windows +// Either seems to work for a font embedded in a PDF file +// when read by Adobe Reader on a Windows PC(!) +if (!defined('_TTF_MAC_HEADER')) { + define('_TTF_MAC_HEADER', false); +} + +// Recalculate correct metadata/profiles when making subset fonts (not SIP/SMP) +// e.g. xMin, xMax, maxNContours +if (!defined('_RECALC_PROFILE')) { + define('_RECALC_PROFILE', false); +} + +// mPDF 5.7.1 +if (!function_exists('\Mpdf\unicode_hex')) { + function unicode_hex($unicode_dec) + { + return sprintf("%05s", strtoupper(dechex($unicode_dec))); + } +} + +/** + * TTFontFile class + * + * This class is based on The ReportLab Open Source PDF library + * written in Python - http://www.reportlab.com/software/opensource/ + * together with ideas from the OpenOffice source code and others. + * This header must be retained in any redistribution or + * modification of the file. + * + * @author Ian Back <ianb@bpm1.com> + * @license LGPL + */ +class TTFontFile +{ + + use Strict; + + private $fontCache; + + private $fontDescriptor; + + var $GPOSFeatures; + + var $GPOSLookups; + + var $GPOSScriptLang; + + var $MarkAttachmentType; + + var $MarkGlyphSets; + + var $GlyphClassMarks; + + var $GlyphClassLigatures; + + var $GlyphClassBases; + + var $GlyphClassComponents; + + var $GSUBScriptLang; + + var $rtlPUAstr; + + var $fontkey; + + var $useOTL; + + var $maxUni; + + var $sFamilyClass; + + var $sFamilySubClass; + + var $sipset; + + var $smpset; + + var $_pos; + + var $numTables; + + var $searchRange; + + var $entrySelector; + + var $rangeShift; + + var $tables; + + var $otables; + + var $filename; + + var $fh; + + var $glyphPos; + + var $charToGlyph; + + var $ascent; + + var $descent; + + var $lineGap; + + var $hheaascent; + + var $hheadescent; + + var $hhealineGap; + + var $advanceWidthMax; + + var $typoAscender; + + var $typoDescender; + + var $typoLineGap; + + var $usWinAscent; + + var $usWinDescent; + + var $strikeoutSize; + + var $strikeoutPosition; + + var $name; + + var $familyName; + + var $styleName; + + var $fullName; + + var $uniqueFontID; + + var $unitsPerEm; + + var $bbox; + + var $capHeight; + + var $xHeight; + + var $stemV; + + var $italicAngle; + + var $flags; + + var $underlinePosition; + + var $underlineThickness; + + var $charWidths; + + var $defaultWidth; + + var $maxStrLenRead; + + var $numTTCFonts; + + var $TTCFonts; + + var $maxUniChar; + + var $kerninfo; + + var $haskernGPOS; + + var $hassmallcapsGSUB; + + var $codeToGlyph; + + var $glyphdata; + + var $LuCoverage; + + public $panose; + + public $version; + + public $fontRevision; + + public $restrictedUse; + + public $glyphIDtoUni; + + public $glyphToChar; + + public $GSUBFeatures; + + public $GSUBLookups; + + public $GSLuCoverage; + + public function __construct(FontCache $fontCache, $fontDescriptor) + { + $this->fontCache = $fontCache; + $this->fontDescriptor = $fontDescriptor; + + // Maximum size of glyf table to read in as string (otherwise reads each glyph from file) + $this->maxStrLenRead = 200000; + } + + public function getMetrics($file, $fontkey, $TTCfontID = 0, $debug = false, $BMPonly = false, $useOTL = 0) + { + $this->useOTL = $useOTL; + $this->fontkey = $fontkey; + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open font file "%s"', $file)); + } + + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->kerninfo = []; + $this->haskernGPOS = []; + $this->hassmallcapsGSUB = []; + $this->ascent = 0; + $this->descent = 0; + $this->lineGap = 0; + $this->hheaascent = 0; + $this->hheadescent = 0; + $this->hhealineGap = 0; + $this->xHeight = 0; + $this->capHeight = 0; + $this->panose = []; + $this->sFamilyClass = 0; + $this->sFamilySubClass = 0; + $this->typoAscender = 0; + $this->typoDescender = 0; + $this->typoLineGap = 0; + $this->usWinAscent = 0; + $this->usWinDescent = 0; + $this->advanceWidthMax = 0; + $this->strikeoutSize = 0; + $this->strikeoutPosition = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->version = $version = $this->read_ulong(); + $this->panose = []; + + if ($version === 0x4F54544F) { + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); + } + + if ($version === 0x74746366 && !$TTCfontID) { + throw new \Mpdf\Exception\FontException(sprintf('TTCfontID for a TrueType Collection is not defined in mPDF "fontdata" configuration (%s)', $file)); + } + + if (!in_array($version, [0x00010000, 0x74727565], true) && !$TTCfontID) { + throw new \Mpdf\Exception\FontException(sprintf('Not a TrueType font: version=%s)', $version)); + } + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000], true)) { + throw new \Mpdf\Exception\FontException(sprintf('Error parsing TrueType Collection: version=%s - (%s)', $version, $file)); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + + $this->readTableDirectory($debug); + $this->extractInfo($debug, $BMPonly, $useOTL); + + fclose($this->fh); + } + + function readTableDirectory($debug = false) + { + $this->numTables = $this->read_ushort(); + $this->searchRange = $this->read_ushort(); + $this->entrySelector = $this->read_ushort(); + $this->rangeShift = $this->read_ushort(); + $this->tables = []; + + for ($i = 0; $i < $this->numTables; $i++) { + $record = []; + $record['tag'] = $this->read_tag(); + $record['checksum'] = [$this->read_ushort(), $this->read_ushort()]; + $record['offset'] = $this->read_ulong(); + $record['length'] = $this->read_ulong(); + $this->tables[$record['tag']] = $record; + } + + if ($debug) { + $this->checksumTables(); + } + } + + function checksumTables() + { + // Check the checksums for all tables + foreach ($this->tables as $t) { + if ($t['length'] > 0 && $t['length'] < $this->maxStrLenRead) { // 1.02 + $table = $this->get_chunk($t['offset'], $t['length']); + $checksum = $this->calcChecksum($table); + if ($t['tag'] === 'head') { + $up = unpack('n*', substr($table, 8, 4)); + $adjustment[0] = $up[1]; + $adjustment[1] = $up[2]; + $checksum = $this->sub32($checksum, $adjustment); + } + $xchecksum = $t['checksum']; + if ($xchecksum != $checksum) { + throw new \Mpdf\Exception\FontException(sprintf('TTF file "%s": invalid checksum %s table: %s (expected %s)', $this->filename, dechex($checksum[0]) . dechex($checksum[1]), $t['tag'], dechex($xchecksum[0]) . dechex($xchecksum[1]))); + } + } + } + } + + function sub32($x, $y) + { + $xlo = $x[1]; + $xhi = $x[0]; + $ylo = $y[1]; + $yhi = $y[0]; + + if ($ylo > $xlo) { + $xlo += 1 << 16; + ++$yhi; + } + $reslo = $xlo - $ylo; + if ($yhi > $xhi) { + $xhi += 1 << 16; + } + $reshi = $xhi - $yhi; + $reshi &= 0xFFFF; + + return [$reshi, $reslo]; + } + + function calcChecksum($data) + { + if (strlen($data) % 4) { + $data .= str_repeat("\0", 4 - (strlen($data) % 4)); + } + + $len = strlen($data); + $hi = 0x0000; + $lo = 0x0000; + + for ($i = 0; $i < $len; $i += 4) { + $hi += (ord($data[$i]) << 8) + ord($data[$i + 1]); + $lo += (ord($data[$i + 2]) << 8) + ord($data[$i + 3]); + $hi += ($lo >> 16) & 0xFFFF; + $lo &= 0xFFFF; + } + + $hi &= 0xFFFF; + + return [$hi, $lo]; + } + + function get_table_pos($tag) + { + if (!isset($this->tables[$tag])) { + return [0, 0]; + } + $offset = $this->tables[$tag]['offset']; + $length = $this->tables[$tag]['length']; + + return [$offset, $length]; + } + + function seek($pos) + { + $this->_pos = $pos; + fseek($this->fh, $this->_pos); + } + + function skip($delta) + { + $this->_pos = $this->_pos + $delta; + fseek($this->fh, $delta, SEEK_CUR); + } + + function seek_table($tag, $offset_in_table = 0) + { + $tpos = $this->get_table_pos($tag); + $this->_pos = $tpos[0] + $offset_in_table; + fseek($this->fh, $this->_pos); + + return $this->_pos; + } + + function read_tag() + { + $this->_pos += 4; + + return fread($this->fh, 4); + } + + function read_short() + { + $this->_pos += 2; + $s = fread($this->fh, 2); + $a = (ord($s[0]) << 8) + ord($s[1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + + return $a; + } + + function unpack_short($s) + { + $a = (ord($s[0]) << 8) + ord($s[1]); + if ($a & (1 << 15)) { + $a = ($a - (1 << 16)); + } + + return $a; + } + + function read_ushort() + { + $this->_pos += 2; + $s = fread($this->fh, 2); + + return (ord($s[0]) << 8) + ord($s[1]); + } + + function read_ulong() + { + $this->_pos += 4; + $s = fread($this->fh, 4); + + // if large uInt32 as an integer, PHP converts it to -ve + return (ord($s[0]) * 16777216) + (ord($s[1]) << 16) + (ord($s[2]) << 8) + ord($s[3]); // 16777216 = 1<<24 + } + + function get_ushort($pos) + { + fseek($this->fh, $pos); + $s = fread($this->fh, 2); + + return (ord($s[0]) << 8) + ord($s[1]); + } + + function get_ulong($pos) + { + fseek($this->fh, $pos); + $s = fread($this->fh, 4); + + // iF large uInt32 as an integer, PHP converts it to -ve + return (ord($s[0]) * 16777216) + (ord($s[1]) << 16) + (ord($s[2]) << 8) + ord($s[3]); // 16777216 = 1<<24 + } + + function pack_short($val) + { + if ($val < 0) { + $val = abs($val); + $val = ~$val; + ++$val; + } + + return pack('n', $val); + } + + function splice($stream, $offset, $value) + { + return substr($stream, 0, $offset) . $value . substr($stream, $offset + strlen($value)); + } + + function _set_ushort($stream, $offset, $value) + { + $up = pack("n", $value); + + return $this->splice($stream, $offset, $up); + } + + function _set_short($stream, $offset, $val) + { + if ($val < 0) { + $val = abs($val); + $val = ~$val; + $val += 1; + } + $up = pack("n", $val); + + return $this->splice($stream, $offset, $up); + } + + function get_chunk($pos, $length) + { + fseek($this->fh, $pos); + if ($length < 1) { + return ''; + } + + $data = (fread($this->fh, $length)); + + // fix for #1504 + // if fread is used to read from a compressed / buffered stream (e.g. phar://...) + // the $length parameter will be ignored - fread is limited in size (usually 8192 bytes) + // to fix this, the data length must be checked after reading. If the read was incomplete, + // try to read the rest of the data + $dataLen = strlen($data); + while ($dataLen < $length && !feof($this->fh)) { + $data .= fread($this->fh, $length - $dataLen); + $dataLen = strlen($data); + } + return $data; + } + + function get_table($tag) + { + list($pos, $length) = $this->get_table_pos($tag); + if ($length == 0) { + return ''; + } + fseek($this->fh, $pos); + + return (fread($this->fh, $length)); + } + + function add($tag, $data) + { + if ($tag === 'head') { + $data = $this->splice($data, 8, "\0\0\0\0"); + } + $this->otables[$tag] = $data; + } + + function getCTG($file, $TTCfontID = 0, $debug = false, $useOTL = false) + { + // Only called if font is not to be used as embedded subset i.e. NOT called for SIP/SMP fonts + $this->useOTL = $useOTL; // mPDF 5.7.1 + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file "%s"', $file)); + } + + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->skip(4); + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000], true)) { + throw new \Mpdf\Exception\FontException(sprintf("Error parsing TrueType Collection: version=%s (%s)", $version, $file)); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + $this->readTableDirectory($debug); + + // cmap - Character to glyph index mapping table + $cmap_offset = $this->seek_table('cmap'); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if ($platformID == 3 && $encodingID == 1) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } elseif ($platformID == 0) { // Unicode -- assume all encodings are compatible + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + $this->seek($save_pos); + } + + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + + // Map Unmapped glyphs - from $numGlyphs + if ($useOTL) { + $this->seek_table("maxp"); + $this->skip(4); + $numGlyphs = $this->read_ushort(); + $bctr = 0xE000; + for ($gid = 1; $gid < $numGlyphs; $gid++) { + if (!isset($glyphToChar[$gid])) { + while (isset($charToGlyph[$bctr])) { + $bctr++; + } // Avoid overwriting a glyph already mapped in PUA + if ($bctr > 0xF8FF) { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" cannot map all included glyphs into Private Use Area U+E000-U+F8FF; cannot use useOTL on this font', $file)); + } + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $bctr++; + } + } + } + + fclose($this->fh); + + return $charToGlyph; + } + + function getTTCFonts($file) + { + $this->filename = $file; + + $this->fh = fopen($file, 'rb'); + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file "%s"', $file)); + } + + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->version = $version = $this->read_ulong(); + if ($version === 0x74746366) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000], true)) { + throw new \Mpdf\Exception\FontException(sprintf("Error parsing TrueType Collection: version=%s (%s)", $version, $file)); + } + } else { + throw new \Mpdf\Exception\FontException(sprintf("Not a TrueType Collection: version=%s (%s)", $version, $file)); + } + + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + } + + function extractInfo($debug = false, $BMPonly = false, $useOTL = 0) + { + // Values are all set to 0 or blank at start of getMetrics + // name - Naming table + $name_offset = $this->seek_table("name"); + $format = $this->read_ushort(); + if ($format != 0 && $format != 1) { + throw new \Mpdf\Exception\FontException("Error loading font: Unknown name table format $format for font $this->filename"); + } + + $numRecords = $this->read_ushort(); + $string_data_offset = $name_offset + $this->read_ushort(); + $names = [1 => '', 2 => '', 3 => '', 4 => '', 6 => '']; + $K = array_keys($names); + $nameCount = count($names); + + for ($i = 0; $i < $numRecords; $i++) { + + $platformId = $this->read_ushort(); + $encodingId = $this->read_ushort(); + $languageId = $this->read_ushort(); + $nameId = $this->read_ushort(); + $length = $this->read_ushort(); + $offset = $this->read_ushort(); + + if (!in_array($nameId, $K)) { + continue; + } + + $N = ''; + if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name + $opos = $this->_pos; + $this->seek($string_data_offset + $offset); + if ($length % 2 != 0) { + throw new \Mpdf\Exception\FontException("Error loading font: PostScript name is UTF-16BE string of odd length for font $this->filename"); + } + $length /= 2; + $N = ''; + while ($length > 0) { + $char = $this->read_ushort(); + $N .= (chr($char)); + $length -= 1; + } + $this->_pos = $opos; + $this->seek($opos); + } elseif ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name + $opos = $this->_pos; + $N = $this->get_chunk($string_data_offset + $offset, $length); + $this->_pos = $opos; + $this->seek($opos); + } + if ($N && $names[$nameId] == '') { + $names[$nameId] = $N; + $nameCount -= 1; + if ($nameCount == 0) { + break; + } + } + } + + if ($names[6]) { + $psName = $names[6]; + } elseif ($names[4]) { + $psName = preg_replace('/ /', '-', $names[4]); + } elseif ($names[1]) { + $psName = preg_replace('/ /', '-', $names[1]); + } else { + $psName = ''; + } + + if (!$psName) { + throw new \Mpdf\Exception\FontException("Error loading font: Could not find PostScript font name '$this->filename'"); + } + + // CHECK IF psName valid (PadaukBook contains illegal characters in Name ID 6 i.e. Postscript Name) + $psNameInvalid = false; + $nameLength = strlen($psName); + for ($i = 0; $i < $nameLength; $i++) { + $c = $psName[$i]; + $oc = ord($c); + if ($oc > 126 || strpos(' [](){}<>/%', $c) !== false) { + //throw new \Mpdf\Exception\FontException("psName=".$psName." contains invalid character ".$c." ie U+".ord(c)); + $psNameInvalid = true; + break; + } + } + + if ($psNameInvalid && $names[4]) { + $psName = preg_replace('/ /', '-', $names[4]); + } + + $this->name = $psName; + if ($names[1]) { + $this->familyName = $names[1]; + } else { + $this->familyName = $psName; + } + if ($names[2]) { + $this->styleName = $names[2]; + } else { + $this->styleName = 'Regular'; + } + if ($names[4]) { + $this->fullName = $names[4]; + } else { + $this->fullName = $psName; + } + if ($names[3]) { + $this->uniqueFontID = $names[3]; + } else { + $this->uniqueFontID = $psName; + } + + if (!$psNameInvalid && $names[6]) { + $this->fullName = $names[6]; + } + + // head - Font header table + $this->seek_table('head'); + if ($debug) { + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException('Error loading font: Unknown head table version ' . $ver_maj . '.' . $ver_min); + } + $this->fontRevision = $this->read_ushort() . $this->read_ushort(); + + $this->skip(4); + $magic = $this->read_ulong(); + if ($magic !== 0x5F0F3CF5) { + throw new \Mpdf\Exception\FontException('Error loading font: Invalid head table magic ' . $magic); + } + $this->skip(2); + } else { + $this->skip(18); + } + $this->unitsPerEm = $unitsPerEm = $this->read_ushort(); + $scale = 1000 / $unitsPerEm; + $this->skip(16); + $xMin = $this->read_short(); + $yMin = $this->read_short(); + $xMax = $this->read_short(); + $yMax = $this->read_short(); + $this->bbox = [($xMin * $scale), ($yMin * $scale), ($xMax * $scale), ($yMax * $scale)]; + + $this->skip(3 * 2); + $indexToLocFormat = $this->read_ushort(); + $glyphDataFormat = $this->read_ushort(); + if ($glyphDataFormat != 0) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown glyph data format %s', $glyphDataFormat)); + } + + // hhea metrics table + if (isset($this->tables["hhea"])) { + $this->seek_table("hhea"); + $this->skip(4); + $hheaAscender = $this->read_short(); + $hheaDescender = $this->read_short(); + $hheaLineGap = $this->read_short(); + $hheaAdvanceWidthMax = $this->read_ushort(); + $this->hheaascent = ($hheaAscender * $scale); + $this->hheadescent = ($hheaDescender * $scale); + $this->hhealineGap = ($hheaLineGap * $scale); + $this->advanceWidthMax = ($hheaAdvanceWidthMax * $scale); + } + + // OS/2 - OS/2 and Windows metrics table + $use_typo_metrics = false; + if (isset($this->tables["OS/2"])) { + $this->seek_table("OS/2"); + $version = $this->read_ushort(); + $this->skip(2); + $usWeightClass = $this->read_ushort(); + $this->skip(2); + $fsType = $this->read_ushort(); + if ($fsType == 0x0002 || ($fsType & 0x0300) != 0) { + $this->restrictedUse = true; + } + + $this->skip(16); + $yStrikeoutSize = $this->read_short(); + $yStrikeoutPosition = $this->read_short(); + $this->strikeoutSize = ($yStrikeoutSize * $scale); + $this->strikeoutPosition = ($yStrikeoutPosition * $scale); + + $sF = $this->read_short(); + $this->sFamilyClass = ($sF >> 8); + $this->sFamilySubClass = ($sF & 0xFF); + $this->_pos += 10; //PANOSE = 10 byte length + $panose = fread($this->fh, 10); + $this->panose = []; + $panoseLenght = strlen($panose); + for ($p = 0; $p < $panoseLenght; $p++) { + $this->panose[] = ord($panose[$p]); + } + + $this->skip(20); + $fsSelection = $this->read_ushort(); + $use_typo_metrics = (($fsSelection & 0x80) === 0x80); // bit#7 = USE_TYPO_METRICS + $this->skip(4); + + $sTypoAscender = $this->read_short(); + $sTypoDescender = $this->read_short(); + $sTypoLineGap = $this->read_short(); + + if ($sTypoAscender) { + $this->typoAscender = ($sTypoAscender * $scale); + } + if ($sTypoDescender) { + $this->typoDescender = ($sTypoDescender * $scale); + } + if ($sTypoLineGap) { + $this->typoLineGap = ($sTypoLineGap * $scale); + } + + $usWinAscent = $this->read_ushort(); + $usWinDescent = $this->read_ushort(); + if ($usWinAscent) { + $this->usWinAscent = ($usWinAscent * $scale); + } + if ($usWinDescent) { + $this->usWinDescent = ($usWinDescent * $scale); + } + + if ($version > 1) { + $this->skip(8); + $sxHeight = $this->read_short(); + $this->xHeight = ($sxHeight * $scale); + $sCapHeight = $this->read_short(); + $this->capHeight = ($sCapHeight * $scale); + } + } else { + $usWeightClass = 400; + } + $this->stemV = 50 + (int) (($usWeightClass / 65.0) ** 2); + + // FONT DESCRIPTOR METRICS + if ($this->fontDescriptor === 'winTypo') { + $this->ascent = $this->typoAscender; + $this->descent = $this->typoDescender; + $this->lineGap = $this->typoLineGap; + } elseif ($this->fontDescriptor === 'mac') { + $this->ascent = $this->hheaascent; + $this->descent = $this->hheadescent; + $this->lineGap = $this->hhealineGap; + } else { // $this->fontDescriptor === 'win' + $this->ascent = $this->usWinAscent; + $this->descent = -$this->usWinDescent; + $this->lineGap = 0; + + // Special case - if either the winAscent or winDescent are greater than the + // font bounding box yMin yMax, then reduce them accordingly. + // This works with Myanmar Text (Windows 8 version) to give a + // line-height normal that is equivalent to that produced in browsers. + // Also Khmer OS = compatible with MSWord, Wordpad and browser. + if ($this->ascent > $this->bbox[3]) { + $this->ascent = $this->bbox[3]; + } + + if ($this->descent < $this->bbox[1]) { + $this->descent = $this->bbox[1]; + } + + // Override case - if the USE_TYPO_METRICS bit is set on OS/2 fsSelection + // this is telling the font to use the sTypo values and not the usWinAscent values. + // This works as a fix with Cambria Math to give a normal line-height; + // at present, this is the only font I have found with this bit set; + // although note that MS WordPad and windows FF browser uses the big line-height from winAscent + // but Word 2007 get it right + if ($use_typo_metrics && $this->typoAscender) { + $this->ascent = $this->typoAscender; + $this->descent = $this->typoDescender; + $this->lineGap = $this->typoLineGap; + } + } + + // post - PostScript table + $this->seek_table('post'); + if ($debug) { + $ver_maj = $this->read_ushort(); + if ($ver_maj < 1 || $ver_maj > 4) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown post table version %s', $ver_maj)); + } + } else { + $this->skip(4); + } + + $this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0; + $this->underlinePosition = $this->read_short() * $scale; + $this->underlineThickness = $this->read_short() * $scale; + $isFixedPitch = $this->read_ulong(); + + $this->flags = 4; + + if ($this->italicAngle != 0) { + $this->flags |= 64; + } + if ($usWeightClass >= 600) { + $this->flags |= 262144; + } + if ($isFixedPitch) { + $this->flags |= 1; + } + + // hhea - Horizontal header table + $this->seek_table('hhea'); + if ($debug) { + $ver_maj = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown hhea table version %s', $ver_maj)); + } + $this->skip(28); + } else { + $this->skip(32); + } + + $metricDataFormat = $this->read_ushort(); + + if ($metricDataFormat != 0) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown horizontal metric data format "%s"', $metricDataFormat)); + } + + $numberOfHMetrics = $this->read_ushort(); + + if ($numberOfHMetrics == 0) { + throw new \Mpdf\Exception\FontException('Error loading font: Number of horizontal metrics is 0'); + } + + // maxp - Maximum profile table + $this->seek_table('maxp'); + if ($debug) { + $ver_maj = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\Exception\FontException(sprintf('Error loading font: Unknown maxp table version %s', $ver_maj)); + } + } else { + $this->skip(4); + } + $numGlyphs = $this->read_ushort(); + + // cmap - Character to glyph index mapping table + $cmap_offset = $this->seek_table('cmap'); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + if (!$unicode_cmap_offset) { + $unicode_cmap_offset = $cmap_offset + $offset; + } + if ($BMPonly) { + break; + } + } + } elseif ((($platformID == 3 && $encodingID == 10) || $platformID == 0) && !$BMPonly) { // Microsoft, Unicode Format 12 table HKCS + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 12) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)', $this->filename)); + } + + $sipset = false; + $smpset = false; + + $this->rtlPUAstr = ''; + $this->GSUBScriptLang = []; + $this->GSUBFeatures = []; + $this->GSUBLookups = []; + $this->GPOSScriptLang = []; + $this->GPOSFeatures = []; + $this->GPOSLookups = []; + $this->glyphIDtoUni = ''; + + // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above + if ($format == 12 && !$BMPonly) { + $this->maxUniChar = 0; + $this->seek($unicode_cmap_offset + 4); + $length = $this->read_ulong(); + $limit = $unicode_cmap_offset + $length; + $this->skip(4); + + $nGroups = $this->read_ulong(); + + $glyphToChar = []; + $charToGlyph = []; + for ($i = 0; $i < $nGroups; $i++) { + $startCharCode = $this->read_ulong(); + $endCharCode = $this->read_ulong(); + $startGlyphCode = $this->read_ulong(); + // ZZZ98 + if ($endCharCode > 0x20000 && $endCharCode < 0x2FFFF) { + $sipset = true; + } elseif ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) { + $smpset = true; + } + $offset = 0; + for ($unichar = $startCharCode; $unichar <= $endCharCode; $unichar++) { + $glyph = $startGlyphCode + $offset; + $offset++; + // ZZZ98 + if ($unichar < 0x30000) { + $charToGlyph[$unichar] = $glyph; + $this->maxUniChar = max($unichar, $this->maxUniChar); + $glyphToChar[$glyph][] = $unichar; + } + } + } + } else { + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + } + $this->sipset = $sipset; + $this->smpset = $smpset; + + // Map Unmapped glyphs (or glyphs mapped to upper PUA U+F00000 onwards i.e. > U+2FFFF) - from $numGlyphs + if ($this->useOTL) { + + $bctr = 0xE000; + + for ($gid = 1; $gid < $numGlyphs; $gid++) { + + if (!isset($glyphToChar[$gid])) { + + while (isset($charToGlyph[$bctr])) { + $bctr++; + } + + // Avoid overwriting a glyph already mapped in PUA + // ZZZ98 + if (($bctr > 0xF8FF) && ($bctr < 0x2CEB0)) { + if (!$BMPonly) { + $bctr = 0x2CEB0; // Use unassigned area 0x2CEB0 to 0x2F7FF (space for 10,000 characters) + $this->sipset = $sipset = true; // forces subsetting; also ensure charwidths are saved + while (isset($charToGlyph[$bctr])) { + $bctr++; + } + } else { + throw new \Mpdf\Exception\FontException(sprintf('The font "%s" does not have enough space to map all (unmapped) included glyphs into Private Use Area U+E000-U+F8FF', $names[1])); + } + } + + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $this->maxUniChar = max($bctr, $this->maxUniChar); + $bctr++; + } + } + } + + $this->glyphToChar = $glyphToChar; + + $this->GSUBScriptLang = []; + $this->rtlPUAstr = ''; + if ($useOTL) { + $this->_getGDEFtables(); + list($this->GSUBScriptLang, $this->GSUBFeatures, $this->GSUBLookups, $this->rtlPUAstr) = $this->_getGSUBtables(); + list($this->GPOSScriptLang, $this->GPOSFeatures, $this->GPOSLookups) = $this->_getGPOStables(); + $this->glyphIDtoUni = str_pad('', 256 * 256 * 3, "\x00"); + foreach ($glyphToChar as $gid => $arr) { + if (isset($glyphToChar[$gid][0])) { + $char = $glyphToChar[$gid][0]; + + if ($char != 0 && $char != 65535) { + $this->glyphIDtoUni[$gid * 3] = chr($char >> 16); + $this->glyphIDtoUni[$gid * 3 + 1] = chr(($char >> 8) & 0xFF); + $this->glyphIDtoUni[$gid * 3 + 2] = chr($char & 0xFF); + } + } + } + } + + // if xHeight and/or CapHeight are not available from OS/2 (e.g. eraly versions) + // Calculate from yMax of 'x' or 'H' Glyphs... + if ($this->xHeight == 0) { + if (isset($charToGlyph[0x78])) { + $gidx = $charToGlyph[0x78]; // U+0078 (LATIN SMALL LETTER X) + $start = $this->seek_table('loca'); + if ($indexToLocFormat == 0) { + $this->skip($gidx * 2); + $locax = $this->read_ushort() * 2; + } elseif ($indexToLocFormat == 1) { + $this->skip($gidx * 4); + $locax = $this->read_ulong(); + } + $start = $this->seek_table('glyf'); + $this->skip($locax); + $this->skip(8); + $yMaxx = $this->read_short(); + $this->xHeight = $yMaxx * $scale; + } + } + + if ($this->capHeight == 0) { + if (isset($charToGlyph[0x48])) { + $gidH = $charToGlyph[0x48]; // U+0048 (LATIN CAPITAL LETTER H) + $start = $this->seek_table('loca'); + if ($indexToLocFormat == 0) { + $this->skip($gidH * 2); + $locaH = $this->read_ushort() * 2; + } elseif ($indexToLocFormat == 1) { + $this->skip($gidH * 4); + $locaH = $this->read_ulong(); + } + $start = $this->seek_table('glyf'); + $this->skip($locaH); + $this->skip(8); + $yMaxH = $this->read_short(); + $this->capHeight = $yMaxH * $scale; + } else { + $this->capHeight = $this->ascent; + } + // final default is to set it = to Ascent + } + + // hmtx - Horizontal metrics table + $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale); + + // kern - Kerning pair table + // Recognises old form of Kerning table - as required by Windows - Format 0 only + $kern_offset = $this->seek_table("kern"); + $version = $this->read_ushort(); + $nTables = $this->read_ushort(); + + // subtable header + $sversion = $this->read_ushort(); + $slength = $this->read_ushort(); + $scoverage = $this->read_ushort(); + $format = $scoverage >> 8; + if ($kern_offset && $version == 0 && $format == 0) { + // Format 0 + $nPairs = $this->read_ushort(); + $this->skip(6); + for ($i = 0; $i < $nPairs; $i++) { + $left = $this->read_ushort(); + $right = $this->read_ushort(); + $val = $this->read_short(); + if (isset($glyphToChar[$left]) && count($glyphToChar[$left]) == 1 && isset($glyphToChar[$right]) && count($glyphToChar[$right]) == 1) { + if ($left != 32 && $right != 32) { + $this->kerninfo[$glyphToChar[$left][0]][$glyphToChar[$right][0]] = intval($val * $scale); + } + } + } + } + } + + function _getGDEFtables() + { + // http://www.microsoft.com/typography/otspec/gdef.htm + if (isset($this->tables["GDEF"])) { + $gdef_offset = $this->seek_table("GDEF"); + + // ULONG Version of the GDEF table-currently 0x00010000 + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + $GlyphClassDef_offset = $this->read_ushort(); + $AttachList_offset = $this->read_ushort(); + $LigCaretList_offset = $this->read_ushort(); + $MarkAttachClassDef_offset = $this->read_ushort(); + + // Version 0x00010002 of GDEF header contains additional Offset to a list defining mark glyph set definitions (MarkGlyphSetDef) + if ($ver_min == 2) { + $MarkGlyphSetsDef_offset = $this->read_ushort(); + } + + // GlyphClassDef + if ($GlyphClassDef_offset) { + + $this->seek($gdef_offset + $GlyphClassDef_offset); + // 1 Base glyph (single character, spacing glyph) + // 2 Ligature glyph (multiple character, spacing glyph) + // 3 Mark glyph (non-spacing combining glyph) + // 4 Component glyph (part of single character, spacing glyph) + $GlyphByClass = $this->_getClassDefinitionTable(); + } else { + $GlyphByClass = []; + } + + if (isset($GlyphByClass[1]) && count($GlyphByClass[1]) > 0) { + $this->GlyphClassBases = ' ' . implode('| ', $GlyphByClass[1]); + } else { + $this->GlyphClassBases = ''; + } + if (isset($GlyphByClass[2]) && count($GlyphByClass[2]) > 0) { + $this->GlyphClassLigatures = ' ' . implode('| ', $GlyphByClass[2]); + } else { + $this->GlyphClassLigatures = ''; + } + if (isset($GlyphByClass[3]) && count($GlyphByClass[3]) > 0) { + $this->GlyphClassMarks = ' ' . implode('| ', $GlyphByClass[3]); + } else { + $this->GlyphClassMarks = ''; + } + if (isset($GlyphByClass[4]) && count($GlyphByClass[4]) > 0) { + $this->GlyphClassComponents = ' ' . implode('| ', $GlyphByClass[4]); + } else { + $this->GlyphClassComponents = ''; + } + + if (isset($GlyphByClass[3]) && count($GlyphByClass[3]) > 0) { + $Marks = $GlyphByClass[3]; + } else { // to use for MarkAttachmentType + $Marks = []; + } + + /* Required for GPOS + // Attachment List + if ($AttachList_offset) { + $this->seek($gdef_offset+$AttachList_offset ); + } + The Attachment Point List table (AttachmentList) identifies all the attachment points defined in the GPOS table and their associated glyphs so a client can quickly access coordinates for each glyph's attachment points. As a result, the client can cache coordinates for attachment points along with glyph bitmaps and avoid recalculating the attachment points each time it displays a glyph. Without this table, processing speed would be slower because the client would have to decode the GPOS lookups that define attachment points and compile the points in a list. + + The Attachment List table (AttachList) may be used to cache attachment point coordinates along with glyph bitmaps. + + The table consists of an offset to a Coverage table (Coverage) listing all glyphs that define attachment points in the GPOS table, a count of the glyphs with attachment points (GlyphCount), and an array of offsets to AttachPoint tables (AttachPoint). The array lists the AttachPoint tables, one for each glyph in the Coverage table, in the same order as the Coverage Index. + AttachList table + Type Name Description + Offset Coverage Offset to Coverage table - from beginning of AttachList table + uint16 GlyphCount Number of glyphs with attachment points + Offset AttachPoint[GlyphCount] Array of offsets to AttachPoint tables-from beginning of AttachList table-in Coverage Index order + + An AttachPoint table consists of a count of the attachment points on a single glyph (PointCount) and an array of contour indices of those points (PointIndex), listed in increasing numerical order. + + AttachPoint table + Type Name Description + uint16 PointCount Number of attachment points on this glyph + uint16 PointIndex[PointCount] Array of contour point indices -in increasing numerical order + + See Example 3 - http://www.microsoft.com/typography/otspec/gdef.htm + */ + + // Ligature Caret List + // The Ligature Caret List table (LigCaretList) defines caret positions for all the ligatures in a font. + // Not required for mDPF + // MarkAttachmentType + if ($MarkAttachClassDef_offset) { + $this->seek($gdef_offset + $MarkAttachClassDef_offset); + $MarkAttachmentTypes = $this->_getClassDefinitionTable(); + foreach ($MarkAttachmentTypes as $class => $glyphs) { + if (is_array($Marks) && count($Marks)) { + $mat = array_diff($Marks, $MarkAttachmentTypes[$class]); + sort($mat, SORT_STRING); + } else { + $mat = []; + } + + $this->MarkAttachmentType[$class] = ' ' . implode('| ', $mat); + } + } else { + $this->MarkAttachmentType = []; + } + + // MarkGlyphSets only in Version 0x00010002 of GDEF + if ($ver_min == 2 && $MarkGlyphSetsDef_offset) { + $this->seek($gdef_offset + $MarkGlyphSetsDef_offset); + $MarkSetTableFormat = $this->read_ushort(); + $MarkSetCount = $this->read_ushort(); + $MarkSetOffset = []; + for ($i = 0; $i < $MarkSetCount; $i++) { + $MarkSetOffset[] = $this->read_ulong(); + } + for ($i = 0; $i < $MarkSetCount; $i++) { + $this->seek($MarkSetOffset[$i]); + $glyphs = $this->_getCoverage(); + $this->MarkGlyphSets[$i] = ' ' . implode('| ', $glyphs); + } + } else { + $this->MarkGlyphSets = []; + } + } else { + throw new \Mpdf\Exception\FontException(sprintf('Unable to set font "%s" to use OTL as it does not include OTL tables (or at least not a GDEF table).', $this->filename)); + } + + $GSUB_offset = 0; + $GPOS_offset = 0; + $GSUB_length = 0; + + $s = ''; + + if (isset($this->tables['GSUB'])) { + $GSUB_offset = $this->seek_table('GSUB'); + $GSUB_length = $this->tables['GSUB']['length']; + $s .= fread($this->fh, $this->tables['GSUB']['length']); + } + + if (isset($this->tables['GPOS'])) { + $GPOS_offset = $this->seek_table('GPOS'); + $s .= fread($this->fh, $this->tables['GPOS']['length']); + } + + if ($s) { + $this->fontCache->write($this->fontkey . '.GSUBGPOStables.dat', $s); + } + + $font = [ + 'GSUB_offset' => $GSUB_offset, + 'GPOS_offset' => $GPOS_offset, + 'GSUB_length' => $GSUB_length, + 'GlyphClassBases' => $this->GlyphClassBases, + 'GlyphClassMarks' => $this->GlyphClassMarks, + 'GlyphClassLigatures' => $this->GlyphClassLigatures, + 'GlyphClassComponents' => $this->GlyphClassComponents, + 'MarkGlyphSets' => $this->MarkGlyphSets, + 'MarkAttachmentType' => $this->MarkAttachmentType, + ]; + + $this->fontCache->jsonWrite($this->fontkey . '.GDEFdata.json', $font); + } + + function _getClassDefinitionTable() + { + // NB Any glyph not included in the range of covered GlyphIDs automatically belongs to Class 0. This is not returned by this function + $ClassFormat = $this->read_ushort(); + $GlyphByClass = []; + + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $gid = $StartGlyph + $i; + $class = $this->read_ushort(); + // Several fonts (mainly dejavu.../Freeserif etc) have a MarkAttachClassDef Format 1, where StartGlyph is 0 and GlyphCount is 1 + // This doesn't seem to do anything useful? + // Freeserif does not have $this->glyphToChar[0] allocated and would throw an error, so check if isset: + if (isset($this->glyphToChar[$gid][0])) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]); + } + } + } elseif ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $startGlyphID = $this->read_ushort(); + $endGlyphID = $this->read_ushort(); + $class = $this->read_ushort(); + for ($gid = $startGlyphID; $gid <= $endGlyphID; $gid++) { + if (isset($this->glyphToChar[$gid][0])) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$gid][0]); + } + } + } + } + foreach ($GlyphByClass as $class => $glyphs) { + sort($GlyphByClass[$class], SORT_STRING); // SORT makes it easier to read in development ? order not important ??? + } + ksort($GlyphByClass); + + return $GlyphByClass; + } + + /** + * GSUB - Glyph Substitution + */ + function _getGSUBtables() + { + if (!isset($this->tables['GSUB'])) { + return [[], [], [], '']; + } + + $ffeats = []; + $gsub_offset = $this->seek_table('GSUB'); + $this->skip(4); + $ScriptList_offset = $gsub_offset + $this->read_ushort(); + $FeatureList_offset = $gsub_offset + $this->read_ushort(); + $LookupList_offset = $gsub_offset + $this->read_ushort(); + + // ScriptList + $this->seek($ScriptList_offset); + $ScriptCount = $this->read_ushort(); + for ($i = 0; $i < $ScriptCount; $i++) { + $ScriptTag = $this->read_tag(); // = "beng", "deva" etc. + $ScriptTableOffset = $this->read_ushort(); + $ffeats[$ScriptTag] = $ScriptList_offset + $ScriptTableOffset; + } + + // Script Table + foreach ($ffeats as $t => $o) { + $ls = []; + $this->seek($o); + $DefLangSys_offset = $this->read_ushort(); + if ($DefLangSys_offset > 0) { + $ls['DFLT'] = $DefLangSys_offset + $o; + } + $LangSysCount = $this->read_ushort(); + for ($i = 0; $i < $LangSysCount; $i++) { + $LangTag = $this->read_tag(); // = + $LangTableOffset = $this->read_ushort(); + $ls[$LangTag] = $o + $LangTableOffset; + } + $ffeats[$t] = $ls; + } + + // Get FeatureIndexList + // LangSys Table - from first listed langsys + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = []; + $langsystable_offset = $o; + $this->seek($langsystable_offset); + $LookUpOrder = $this->read_ushort(); //==NULL + $ReqFeatureIndex = $this->read_ushort(); + if ($ReqFeatureIndex != 0xFFFF) { + $FeatureIndex[] = $ReqFeatureIndex; + } + $FeatureCount = $this->read_ushort(); + for ($i = 0; $i < $FeatureCount; $i++) { + $FeatureIndex[] = $this->read_ushort(); // = index of feature + } + $ffeats[$st][$t] = $FeatureIndex; + } + } + + // Feauture List => LookupListIndex es + $this->seek($FeatureList_offset); + $FeatureCount = $this->read_ushort(); + $Feature = []; + + for ($i = 0; $i < $FeatureCount; $i++) { + $tag = $this->read_tag(); + if ($tag == 'smcp') { + $this->hassmallcapsGSUB = true; + } + $Feature[$i] = ['tag' => $tag]; + $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort(); + } + + for ($i = 0; $i < $FeatureCount; $i++) { + $this->seek($Feature[$i]['offset']); + $this->read_ushort(); // null [FeatureParams] + $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort(); + $Feature[$i]['LookupListIndex'] = []; + for ($c = 0; $c < $Lookupcount; $c++) { + $Feature[$i]['LookupListIndex'][] = $this->read_ushort(); + } + } + + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = $ffeats[$st][$t]; + foreach ($FeatureIndex as $k => $fi) { + $ffeats[$st][$t][$k] = $Feature[$fi]; + } + } + } + + $gsub = []; + $GSUBScriptLang = []; + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $langsys) { + $lg = []; + foreach ($langsys as $ft) { + $lg[$ft['LookupListIndex'][0]] = $ft; + } + // list of Lookups in order they need to be run i.e. order listed in Lookup table + ksort($lg); + foreach ($lg as $ft) { + $gsub[$st][$t][$ft['tag']] = $ft['LookupListIndex']; + } + if (!isset($GSUBScriptLang[$st])) { + $GSUBScriptLang[$st] = ''; + } + $GSUBScriptLang[$st] .= $t . ' '; + } + } + + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $GSLookup = []; + $Offsets = []; + $SubtableCount = []; + + for ($i = 0; $i < $LookupCount; $i++) { + $Offsets[$i] = $LookupList_offset + $this->read_ushort(); + } + + for ($i = 0; $i < $LookupCount; $i++) { + + $this->seek($Offsets[$i]); + + $GSLookup[$i]['Type'] = $this->read_ushort(); + $GSLookup[$i]['Flag'] = $flag = $this->read_ushort(); + $GSLookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort(); + + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $GSLookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort(); + } + + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) == 0x0010) { + $GSLookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } else { + $GSLookup[$i]['MarkFilteringSet'] = ''; + } + + // Lookup Type 7: Extension + if ($GSLookup[$i]['Type'] == 7) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $this->seek($GSLookup[$i]['Subtables'][$c]); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $ext_offset = $this->read_ulong(); + $GSLookup[$i]['Subtables'][$c] = $GSLookup[$i]['Subtables'][$c] + $ext_offset; + } + $GSLookup[$i]['Type'] = $type; + } + } + + // Process Whole LookupList - Get LuCoverage = Lookup coverage just for first glyph + $this->GSLuCoverage = []; + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $GSLookup[$i]['SubtableCount']; $c++) { + $this->seek($GSLookup[$i]['Subtables'][$c]); + $PosFormat = $this->read_ushort(); + + if ($GSLookup[$i]['Type'] == 5 && $PosFormat == 3) { + $this->skip(4); + } elseif ($GSLookup[$i]['Type'] == 6 && $PosFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + $this->skip(2 * $BacktrackGlyphCount + 2); + } + + // NB Coverage only looks at glyphs for position 1 (i.e. 5.3 and 6.3) // NEEDS TO READ ALL ******************** + $Coverage = $GSLookup[$i]['Subtables'][$c] + $this->read_ushort(); + $this->seek($Coverage); + $glyphs = $this->_getCoverage(false, 2); + $this->GSLuCoverage[$i][$c] = $glyphs; + } + } + + // $this->GSLuCoverage and $GSLookup + $this->fontCache->jsonWrite($this->fontkey . '.GSUBdata.json', $this->GSLuCoverage); + + // Now repeats as original to get Substitution rules + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $Lookup = []; + + for ($i = 0; $i < $LookupCount; $i++) { + $Lookup[$i]['offset'] = $LookupList_offset + $this->read_ushort(); + } + + for ($i = 0; $i < $LookupCount; $i++) { + $this->seek($Lookup[$i]['offset']); + $Lookup[$i]['Type'] = $this->read_ushort(); + $Lookup[$i]['Flag'] = $flag = $this->read_ushort(); + $Lookup[$i]['SubtableCount'] = $this->read_ushort(); + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['offset'] + $this->read_ushort(); + } + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) == 0x0010) { + $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } else { + $Lookup[$i]['MarkFilteringSet'] = ''; + } + + // Lookup Type 7: Extension + if ($Lookup[$i]['Type'] == 7) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $this->seek($Lookup[$i]['Subtable'][$c]['Offset']); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ulong(); + } + $Lookup[$i]['Type'] = $type; + } + } + + // Process (1) Whole LookupList + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $this->seek($Lookup[$i]['Subtable'][$c]['Offset']); + $SubstFormat = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['Format'] = $SubstFormat; + + /* + Lookup['Type'] Enumeration table for glyph substitution + Value Type Description + 1 Single Replace one glyph with one glyph + 2 Multiple Replace one glyph with more than one glyph + 3 Alternate Replace one glyph with one of many glyphs + 4 Ligature Replace multiple glyphs with one glyph + 5 Context Replace one or more glyphs in context + 6 Chaining Context Replace one or more glyphs in chained context + 7 Extension Substitution Extension mechanism for other substitutions (i.e. this excludes the Extension type substitution itself) + 8 Reverse chaining context single Applied in reverse order, replace single glyph in chaining context + */ + + // LookupType 1: Single Substitution Subtable + if ($Lookup[$i]['Type'] == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + if ($SubstFormat == 1) { // Calculated output glyph indices + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'] = $this->read_short(); + } elseif ($SubstFormat == 2) { // Specified output glyph indices + $GlyphCount = $this->read_ushort(); + for ($g = 0; $g < $GlyphCount; $g++) { + $Lookup[$i]['Subtable'][$c]['Glyphs'][] = $this->read_ushort(); + } + } + } // LookupType 2: Multiple Substitution Subtable + elseif ($Lookup[$i]['Type'] == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SequenceCount'] = $SequenceCount = $this->read_short(); + for ($s = 0; $s < $SequenceCount; $s++) { + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $SequenceCount; $s++) { + // Sequence Tables + $this->seek($Lookup[$i]['Subtable'][$c]['Sequences'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['GlyphCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['GlyphCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['Sequences'][$s]['SubstituteGlyphID'][] = $this->read_ushort(); + } + } + } // LookupType 3: Alternate Forms + elseif ($Lookup[$i]['Type'] == 3) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['AlternateSetCount'] = $AlternateSetCount = $this->read_short(); + for ($s = 0; $s < $AlternateSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + + for ($s = 0; $s < $AlternateSetCount; $s++) { + // AlternateSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['GlyphCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['GlyphCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['AlternateSets'][$s]['SubstituteGlyphID'][] = $this->read_ushort(); + } + } + } // LookupType 4: Ligature Substitution Subtable + elseif ($Lookup[$i]['Type'] == 4) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LigSetCount'] = $LigSetCount = $this->read_short(); + for ($s = 0; $s < $LigSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $LigSetCount; $s++) { + // LigatureSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g] = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Offset'] + $this->read_ushort(); + } + } + for ($s = 0; $s < $LigSetCount; $s++) { + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + // Ligature tables + $this->seek($Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigatureOffset'][$g]); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount'] = $this->read_ushort(); + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['GlyphID'][$l] = $this->read_ushort(); + } + } + } + } // LookupType 5: Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 5) { + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSetCount'] = $SubRuleSetCount = $this->read_short(); + for ($s = 0; $s < $SubRuleSetCount; $s++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_short(); + } + for ($s = 0; $s < $SubRuleSetCount; $s++) { + // SubRuleSet Tables + $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset']); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount'] = $this->read_short(); + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $g++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g] = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['Offset'] + $this->read_ushort(); + } + } + for ($s = 0; $s < $SubRuleSetCount; $s++) { + // SubRule Tables + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $g++) { + // Ligature tables + $this->seek($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleOffset'][$g]); + + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['GlyphCount'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstCount'] = $this->read_ushort(); + // "Input"::[GlyphCount - 1]::Array of input GlyphIDs-start with second glyph + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['GlyphCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['Input'][$l] = $this->read_ushort(); + } + // "SubstLookupRecord"::[SubstCount]::Array of SubstLookupRecords-in design order + for ($l = 0; $l < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstCount']; $l++) { + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['SequenceIndex'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$g]['SubstLookupRecord'][$l]['LookupListIndex'] = $this->read_ushort(); + } + } + } + } // Format 2: Class-based Context Glyph Substitution + elseif ($SubstFormat == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubClassSetCnt'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][] = 0; + } else { + $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $offset; + } + } + } else { + throw new \Mpdf\Exception\FontException("GPOS Lookup Type " . $Lookup[$i]['Type'] . ", Format " . $SubstFormat . " not supported (ttfontsuni.php)."); + } + } // LookupType 6: Chaining Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 6) { + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + elseif ($SubstFormat == 2) { + $Lookup[$i]['Subtable'][$c]['CoverageTableOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['InputClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset'] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $b++) { + $offset = $this->read_ushort(); + if ($offset == 0x0000) { + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][] = $offset; + } else { + $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $offset; + } + } + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + elseif ($SubstFormat == 3) { + $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['InputGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageInput'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['CoverageLookahead'][] = $Lookup[$i]['Subtable'][$c]['Offset'] + $this->read_ushort(); + } + $Lookup[$i]['Subtable'][$c]['SubstCount'] = $this->read_ushort(); + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex'] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex'] = $this->read_ushort(); + // Substitution Lookup Record + // All contextual substitution subtables specify the substitution data in a Substitution Lookup Record + // (SubstLookupRecord). Each record contains a SequenceIndex, which indicates the position where the substitution + // will occur in the glyph sequence. In addition, a LookupListIndex identifies the lookup to be applied at the + // glyph position specified by the SequenceIndex. + } + } + } else { + throw new \Mpdf\Exception\FontException(sprintf('Lookup Type "%s" not supported.', $Lookup[$i]['Type'])); + } + } + } + + // Process (2) Whole LookupList + // Get Coverage tables and prepare preg_replace + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $SubstFormat = $Lookup[$i]['Subtable'][$c]['Format']; + + // LookupType 1: Single Substitution Subtable 1 => 1 + if ($Lookup[$i]['Type'] == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(false); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = unicode_hex($this->glyphToChar[$glyphs[$g]][0]); + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + if (isset($Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])) { // Format 1 + $substitute[] = unicode_hex($this->glyphToChar[($glyphs[$g] + $Lookup[$i]['Subtable'][$c]['DeltaGlyphID'])][0]); + } else { // Format 2 + $substitute[] = unicode_hex($this->glyphToChar[($Lookup[$i]['Subtable'][$c]['Glyphs'][$g])][0]); + } + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + } // LookupType 2: Multiple Substitution Subtable 1 => n + elseif ($Lookup[$i]['Type'] == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$g]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + if (!isset($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID']) || count($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID']) == 0) { + continue; + } // Illegal for GlyphCount to be 0; either error in font, or something has gone wrong - lets carry on for now! + foreach ($Lookup[$i]['Subtable'][$c]['Sequences'][$g]['SubstituteGlyphID'] as $sub) { + $substitute[] = unicode_hex($this->glyphToChar[$sub][0]); + } + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + } // LookupType 3: Alternate Forms 1 => 1 (only first alternate form is used) + elseif ($Lookup[$i]['Type'] == 3) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + for ($g = 0; $g < count($glyphs); $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$g]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + $gid = $Lookup[$i]['Subtable'][$c]['AlternateSets'][$g]['SubstituteGlyphID'][0]; + if (!isset($this->glyphToChar[$gid][0])) { + continue; + } + $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute]; + } + } // LookupType 4: Ligature Substitution Subtable n => 1 + elseif ($Lookup[$i]['Type'] == 4) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $glyphs = $this->_getCoverage(); + $LigSetCount = $Lookup[$i]['Subtable'][$c]['LigSetCount']; + for ($s = 0; $s < $LigSetCount; $s++) { + for ($g = 0; $g < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['LigCount']; $g++) { + $replace = []; + $substitute = []; + $replace[] = $glyphs[$s]; + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $replace[0], $Lookup[$i]['MarkFilteringSet'])) { + continue; + } + for ($l = 1; $l < $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']; $l++) { + $gid = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['GlyphID'][$l]; + $rpl = unicode_hex($this->glyphToChar[$gid][0]); + // Flag = Ignore + if ($this->_checkGSUBignore($Lookup[$i]['Flag'], $rpl, $Lookup[$i]['MarkFilteringSet'])) { + continue 2; + } + $replace[] = $rpl; + } + $gid = $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['LigGlyph']; + if (!isset($this->glyphToChar[$gid][0])) { + continue; + } + $substitute[] = unicode_hex($this->glyphToChar[$gid][0]); + $Lookup[$i]['Subtable'][$c]['subs'][] = ['Replace' => $replace, 'substitute' => $substitute, 'CompCount' => $Lookup[$i]['Subtable'][$c]['LigSet'][$s]['Ligature'][$g]['CompCount']]; + } + } + } // LookupType 5: Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 5) { + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubRuleSetCount']; $s++) { + $SubRuleSet = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]; + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['FirstGlyph'] = $CoverageGlyphs[$s]; + for ($r = 0; $r < $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRuleCount']; $r++) { + $GlyphCount = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['GlyphCount']; + for ($g = 1; $g < $GlyphCount; $g++) { + $glyphID = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['Input'][$g]; + $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + } + } + } // Format 2: Class-based Context Glyph Substitution + elseif ($SubstFormat == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['ClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['InputClasses'] = $InputClasses; + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $s++) { + if ($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s]); + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRuleCnt'] = $SubClassRuleCnt = $this->read_ushort(); + $SubClassRule = []; + for ($b = 0; $b < $SubClassRuleCnt; $b++) { + $SubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b] = $SubClassRule[$b]; + } + } + } + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubClassSetCnt']; $s++) { + if ($Lookup[$i]['Subtable'][$c]['SubClassSetOffset'][$s] > 0) { + $SubClassRuleCnt = $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRuleCnt']; + for ($b = 0; $b < $SubClassRuleCnt; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b]); + $Rule = []; + $Rule['InputGlyphCount'] = $this->read_ushort(); + $Rule['SubstCount'] = $this->read_ushort(); + for ($r = 1; $r < $Rule['InputGlyphCount']; $r++) { + $Rule['Input'][$r] = $this->read_ushort(); + } + for ($r = 0; $r < $Rule['SubstCount']; $r++) { + $Rule['SequenceIndex'][$r] = $this->read_ushort(); + $Rule['LookupListIndex'][$r] = $this->read_ushort(); + } + + $Lookup[$i]['Subtable'][$c]['SubClassSet'][$s]['SubClassRule'][$b] = $Rule; + } + } + } + } // Format 3: Coverage-based Context Glyph Substitution + elseif ($SubstFormat == 3) { + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs'][] = implode("|", $glyphs); + } + throw new \Mpdf\Exception\FontException("Lookup Type 5, SubstFormat 3 not tested. Please report this with the name of font used - " . $this->fontkey); + } + } // LookupType 6: Chaining Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 6) { + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $ChainSubRuleSetCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; + + for ($s = 0; $s < $ChainSubRuleSetCnt; $s++) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s]); + $ChainSubRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleCount'] = $this->read_ushort(); + for ($r = 0; $r < $ChainSubRuleCnt; $r++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r] = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetOffset'][$s] + $this->read_ushort(); + } + } + for ($s = 0; $s < $ChainSubRuleSetCnt; $s++) { + $ChainSubRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleCount']; + for ($r = 0; $r < $ChainSubRuleCnt; $r++) { + // ChainSubRule + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRuleOffset'][$r]); + + $BacktrackGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphCount'] = $this->read_ushort(); + for ($g = 0; $g < $BacktrackGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['BacktrackGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $InputGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphCount'] = $this->read_ushort(); + for ($g = 1; $g < $InputGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['InputGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $LookaheadGlyphCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphCount'] = $this->read_ushort(); + for ($g = 0; $g < $LookaheadGlyphCount; $g++) { + $glyphID = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookaheadGlyphs'][$g] = unicode_hex($this->glyphToChar[$glyphID][0]); + } + + $SubstCount = $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SubstCount'] = $this->read_ushort(); + for ($lu = 0; $lu < $SubstCount; $lu++) { + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['SequenceIndex'][$lu] = $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'][$r]['LookupListIndex'][$lu] = $this->read_ushort(); + } + } + } + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + elseif ($SubstFormat == 2) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageTableOffset']); + $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'] = $CoverageGlyphs = $this->_getCoverage(); + + $BacktrackClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['BacktrackClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['BacktrackClasses'] = $BacktrackClasses; + + $InputClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['InputClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['InputClasses'] = $InputClasses; + + $LookaheadClasses = $this->_getClasses($Lookup[$i]['Subtable'][$c]['LookaheadClassDefOffset']); + $Lookup[$i]['Subtable'][$c]['LookaheadClasses'] = $LookaheadClasses; + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $s++) { + if ($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s]); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt'] = $ChainSubClassRuleCnt = $this->read_ushort(); + $ChainSubClassRule = []; + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { + $ChainSubClassRule[$b] = $Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] + $this->read_ushort(); + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b] = $ChainSubClassRule[$b]; + } + } + } + + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubClassSetCnt']; $s++) { + if (isset($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt'])) { + $ChainSubClassRuleCnt = $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRuleCnt']; + } else { + $ChainSubClassRuleCnt = 0; + } + for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) { + if ($Lookup[$i]['Subtable'][$c]['ChainSubClassSetOffset'][$s] > 0) { + $this->seek($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b]); + $Rule = []; + $Rule['BacktrackGlyphCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['BacktrackGlyphCount']; $r++) { + $Rule['Backtrack'][$r] = $this->read_ushort(); + } + $Rule['InputGlyphCount'] = $this->read_ushort(); + for ($r = 1; $r < $Rule['InputGlyphCount']; $r++) { + $Rule['Input'][$r] = $this->read_ushort(); + } + $Rule['LookaheadGlyphCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['LookaheadGlyphCount']; $r++) { + $Rule['Lookahead'][$r] = $this->read_ushort(); + } + $Rule['SubstCount'] = $this->read_ushort(); + for ($r = 0; $r < $Rule['SubstCount']; $r++) { + $Rule['SequenceIndex'][$r] = $this->read_ushort(); + $Rule['LookupListIndex'][$r] = $this->read_ushort(); + } + + $Lookup[$i]['Subtable'][$c]['ChainSubClassSet'][$s]['ChainSubClassRule'][$b] = $Rule; + } + } + } + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + elseif ($SubstFormat == 3) { + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageBacktrack'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageBacktrackGlyphs'][] = implode("|", $glyphs); + } + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageInput'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs'][] = implode("|", $glyphs); + // Don't use above value as these are ordered numerically not as need to process + } + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']; $b++) { + $this->seek($Lookup[$i]['Subtable'][$c]['CoverageLookahead'][$b]); + $glyphs = $this->_getCoverage(); + $Lookup[$i]['Subtable'][$c]['CoverageLookaheadGlyphs'][] = implode("|", $glyphs); + } + } + } + } + } + + $GSUBScriptLang = []; + $rtlpua = []; // All glyphs added to PUA [for magic_reverse] + foreach ($gsub as $st => $scripts) { + foreach ($scripts as $t => $langsys) { + $lul = []; // array of LookupListIndexes + $tags = []; // corresponding array of feature tags e.g. 'ccmp' + + foreach ($langsys as $tag => $ft) { + foreach ($ft as $ll) { + $lul[$ll] = $tag; + } + } + ksort($lul); // Order the Lookups in the order they are in the GUSB table, regardless of Feature order + $volt = $this->_getGSUBarray($Lookup, $lul, $st); + + // Interrogate $volt + // isol, fin, medi, init(arab syrc) into $rtlSUB for use in ArabJoin + // but also identify all RTL chars in PUA for magic_reverse (arab syrc hebr thaa nko samr) + // identify reph, matras, vatu, half forms etc for Indic for final re-ordering + $rtl = []; + $rtlSUB = []; + $finals = ''; + + if (strpos('arab syrc hebr thaa nko samr', $st) !== false) { // all RTL scripts [any/all languages] ? Mandaic + + foreach ($volt as $v) { + // isol fina fin2 fin3 medi med2 for Syriac + // ISOLATED FORM :: FINAL :: INITIAL :: MEDIAL :: MED2 :: FIN2 :: FIN3 + if (strpos('isol fina init medi fin2 fin3 med2', $v['tag']) !== false) { + + $key = $v['match']; + $key = preg_replace('/[\(\)]*/', '', $key); + $sub = $v['replace']; + if ($v['tag'] === 'isol') { + $kk = 0; + } elseif ($v['tag'] === 'fina') { + $kk = 1; + } elseif ($v['tag'] === 'init') { + $kk = 2; + } elseif ($v['tag'] === 'medi') { + $kk = 3; + } elseif ($v['tag'] === 'med2') { + $kk = 4; + } elseif ($v['tag'] === 'fin2') { + $kk = 5; + } elseif ($v['tag'] === 'fin3') { + $kk = 6; + } + + $rtl[$key][$kk] = $sub; + if (isset($v['prel']) && count($v['prel'])) { + $rtl[$key]['prel'][$kk] = $v['prel']; + } + if (isset($v['postl']) && count($v['postl'])) { + $rtl[$key]['postl'][$kk] = $v['postl']; + } + if (isset($v['ignore']) && $v['ignore']) { + $rtl[$key]['ignore'][$kk] = $v['ignore']; + } + $rtlpua[] = $sub; + + } else { // Add any other glyphs which are in PUA + if (isset($v['context']) && $v['context']) { + foreach ($v['rules'] as $vs) { + $matchCount = count($vs['match']); + for ($i = 0; $i < $matchCount; $i++) { + if (isset($vs['replace'][$i]) && preg_match('/^0[A-F0-9]{4}$/', $vs['match'][$i])) { + if (preg_match('/^0[EF][A-F0-9]{3}$/', $vs['replace'][$i])) { + $rtlpua[] = $vs['replace'][$i]; + } + } + } + } + } else { + preg_match_all('/\((0[A-F0-9]{4})\)/', $v['match'], $m); + $matchCount = count($m[0]); + for ($i = 0; $i < $matchCount; $i++) { + $sb = explode(' ', $v['replace']); + foreach ($sb as $sbg) { + if (preg_match('/(0[EF][A-F0-9]{3})/', $sbg, $mr)) { + $rtlpua[] = $mr[1]; + } + } + } + } + } + } + + // For kashida, need to determine all final forms except ones already identified by kashida priority rules (see \Mpdf\Otl) + foreach ($rtl as $base => $variants) { + if (isset($variants[1])) { // i.e. final form + if (strpos('0FE8E 0FE94 0FEA2 0FEAA 0FEAE 0FEC2 0FEDA 0FEDE 0FB93 0FECA 0FED2 0FED6 0FEEE 0FEF0 0FEF2', $variants[1]) === false) { // not already included + // This version does not exclude RA (0631) FEAE; Ya (064A) FEF2; Alef Maqsurah (0649) FEF0 which + // are selected in priority if connected to a medial Bah + //if (strpos('0FE8E 0FE94 0FEA2 0FEAA 0FEC2 0FEDA 0FEDE 0FB93 0FECA 0FED2 0FED6 0FEEE', $variants[1])===false) { // not already included + $finals .= $variants[1] . ' '; + } + } + } + + ksort($rtl); + $rtlSUB = $rtl; + } + + // INDIC - Dynamic properties + $rphf = []; + $half = []; + $pref = []; + $blwf = []; + $pstf = []; + + if (strpos('dev2 bng2 gur2 gjr2 ory2 tml2 tel2 knd2 mlm2 deva beng guru gujr orya taml telu knda mlym', $st) !== false) { // all INDIC scripts [any/all languages] + if (strpos('deva beng guru gujr orya taml telu knda mlym', $st) !== false) { + $is_old_spec = true; + } else { + $is_old_spec = false; + } + + // First get 'locl' substitutions (reversed!) + $loclsubs = []; + foreach ($volt as $v) { + if (strpos('locl', $v['tag']) !== false) { + $key = $v['match']; + $key = preg_replace('/[\(\)]*/', '', $key); + $sub = $v['replace']; + if ($key && strlen(trim($key)) == 5 && $sub) { + $loclsubs[$sub] = $key; + } + } + } + + foreach ($volt as $v) { + // <rphf> <half> <pref> <blwf> <pstf> + // defines consonant types: + // Reph <rphf> + // Half forms <half> + // Pre-base-reordering forms of Ra/Rra <pref> + // Below-base forms <blwf> + // Post-base forms <pstf> + // applied together with <locl> feature to input sequences consisting of two characters + // This is done for each consonant + // for <rphf> and <half>, features are applied to Consonant + Halant combinations + // for <pref>, <blwf> and <pstf>, features are applied to Halant + Consonant combinations + // Old version eg 'deva' <pref>, <blwf> and <pstf>, features are applied to Consonant + Halant + // Some malformed fonts still do Consonant + Halant for these - so match both?? + // If these two glyphs form a ligature, with no additional glyphs in context + // this means the consonant has the corresponding form + // Currently set to cope with both + // See also classes/otl.php + + if (strpos('rphf half pref blwf pstf', $v['tag']) !== false) { + if (isset($v['context']) && $v['context'] && $v['nBacktrack'] == 0 && $v['nLookahead'] == 0) { + foreach ($v['rules'] as $vs) { + if (count($vs['match']) == 2 && count($vs['replace']) == 1) { + $sub = $vs['replace'][0]; + // If Halant Cons <pref>, <blwf> and <pstf> in New version only + if (strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', $vs['match'][0]) !== false && strpos('pref blwf pstf', $v['tag']) !== false && !$is_old_spec) { + $key = $vs['match'][1]; + $tag = $v['tag']; + if (isset($loclsubs[$key])) { + ${$tag}[$loclsubs[$key]] = $sub; + } + $tmp = &$$tag; + $tmp[hexdec($key)] = hexdec($sub); + } // If Cons Halant <rphf> and <half> always + // and <pref>, <blwf> and <pstf> in Old version + elseif (strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', $vs['match'][1]) !== false && (strpos('rphf half', $v['tag']) !== false || (strpos('pref blwf pstf', $v['tag']) !== false && ($is_old_spec || _OTL_OLD_SPEC_COMPAT_2)))) { + $key = $vs['match'][0]; + $tag = $v['tag']; + if (isset($loclsubs[$key])) { + ${$tag}[$loclsubs[$key]] = $sub; + } + $tmp = &$$tag; + $tmp[hexdec($key)] = hexdec($sub); + } + } + } + } elseif (!isset($v['context'])) { + $key = $v['match']; + $key = preg_replace('/[\(\)]*/', '', $key); + $sub = $v['replace']; + if ($key && strlen(trim($key)) == 11 && $sub) { + // If Cons Halant <rphf> and <half> always + // and <pref>, <blwf> and <pstf> in Old version + // If Halant Cons <pref>, <blwf> and <pstf> in New version only + if (strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', substr($key, 0, 5)) !== false && strpos('pref blwf pstf', $v['tag']) !== false && !$is_old_spec) { + $key = substr($key, 6, 5); + $tag = $v['tag']; + if (isset($loclsubs[$key])) { + ${$tag}[$loclsubs[$key]] = $sub; + } + $tmp = &$$tag; + $tmp[hexdec($key)] = hexdec($sub); + } elseif (strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', substr($key, 6, 5)) !== false && (strpos('rphf half', $v['tag']) !== false || (strpos('pref blwf pstf', $v['tag']) !== false && ($is_old_spec || _OTL_OLD_SPEC_COMPAT_2)))) { + $key = substr($key, 0, 5); + $tag = $v['tag']; + if (isset($loclsubs[$key])) { + ${$tag}[$loclsubs[$key]] = $sub; + } + $tmp = &$$tag; + $tmp[hexdec($key)] = hexdec($sub); + } + } + } + } + } + } + + if (count($rtl) || count($rphf) || count($half) || count($pref) || count($blwf) || count($pstf) || $finals) { + $font = [ + 'rtlSUB' => $rtlSUB, + 'finals' => $finals, + 'rphf' => $rphf, + 'half' => $half, + 'pref' => $pref, + 'blwf' => $blwf, + 'pstf' => $pstf, + ]; + + $this->fontCache->jsonWrite($this->fontkey . '.GSUB.' . $st . '.' . $t . '.json', $font); + } + + if (!isset($GSUBScriptLang[$st])) { + $GSUBScriptLang[$st] = ''; + } + $GSUBScriptLang[$st] .= $t . ' '; + } + } + + // All RTL glyphs from font added to (or already in) PUA [reqd for magic_reverse] + $rtlPUAstr = ''; + if (count($rtlpua)) { + $rtlpua = array_unique($rtlpua); + sort($rtlpua); + $n = count($rtlpua); + for ($i = 0; $i < $n; $i++) { + if (hexdec($rtlpua[$i]) < hexdec('E000') || hexdec($rtlpua[$i]) > hexdec('F8FF')) { + unset($rtlpua[$i]); + } + } + sort($rtlpua, SORT_STRING); + + $rangeid = -1; + $range = []; + $prevgid = -2; + + // for each character + foreach ($rtlpua as $gidhex) { + $gid = hexdec($gidhex); + if ($gid == ($prevgid + 1)) { + $range[$rangeid]['end'] = $gidhex; + $range[$rangeid]['count']++; + } else { + // new range + $rangeid++; + $range[$rangeid] = []; + $range[$rangeid]['start'] = $gidhex; + $range[$rangeid]['end'] = $gidhex; + $range[$rangeid]['count'] = 1; + } + $prevgid = $gid; + } + + foreach ($range as $rg) { + if ($rg['count'] == 1) { + $rtlPUAstr .= "\x{" . $rg['start'] . "}"; + } elseif ($rg['count'] == 2) { + $rtlPUAstr .= "\x{" . $rg['start'] . "}\x{" . $rg['end'] . "}"; + } else { + $rtlPUAstr .= "\x{" . $rg['start'] . "}-\x{" . $rg['end'] . "}"; + } + } + } + + return [$GSUBScriptLang, $gsub, $GSLookup, $rtlPUAstr]; + } + + // GSUB functions + function _getGSUBarray(&$Lookup, &$lul, $scripttag) + { + // Process (3) LookupList for specific Script-LangSys + // Generate preg_replace + $volt = []; + $reph = ''; + $matraE = ''; + $vatu = ''; + + foreach ($lul as $i => $tag) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $SubstFormat = $Lookup[$i]['Subtable'][$c]['Format']; + + // LookupType 1: Single Substitution Subtable + if ($Lookup[$i]['Type'] == 1) { + $subCount = count($Lookup[$i]['Subtable'][$c]['subs']); + for ($s = 0; $s < $subCount; $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + // Ignore has already been applied earlier on + $repl = $this->_makeGSUBinputMatch($inputGlyphs, "()"); + $subs = $this->_makeGSUBinputReplacement(1, $substitute, "()", 0, 1, 0); + $volt[] = ['match' => $repl, 'replace' => $subs, 'tag' => $tag, 'key' => $inputGlyphs[0], 'type' => 1]; + } + } // LookupType 2: Multiple Substitution Subtable + elseif ($Lookup[$i]['Type'] == 2) { + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = implode(" ", $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute']); + // Ignore has already been applied earlier on + $repl = $this->_makeGSUBinputMatch($inputGlyphs, "()"); + $subs = $this->_makeGSUBinputReplacement(1, $substitute, "()", 0, 1, 0); + $volt[] = ['match' => $repl, 'replace' => $subs, 'tag' => $tag, 'key' => $inputGlyphs[0], 'type' => 2]; + } + } // LookupType 3: Alternate Forms + elseif ($Lookup[$i]['Type'] == 3) { + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + // Ignore has already been applied earlier on + $repl = $this->_makeGSUBinputMatch($inputGlyphs, "()"); + $subs = $this->_makeGSUBinputReplacement(1, $substitute, "()", 0, 1, 0); + $volt[] = ['match' => $repl, 'replace' => $subs, 'tag' => $tag, 'key' => $inputGlyphs[0], 'type' => 3]; + } + } // LookupType 4: Ligature Substitution Subtable + elseif ($Lookup[$i]['Type'] == 4) { + for ($s = 0; $s < count($Lookup[$i]['Subtable'][$c]['subs']); $s++) { + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['subs'][$s]['Replace']; + $substitute = $Lookup[$i]['Subtable'][$c]['subs'][$s]['substitute'][0]; + // Ignore has already been applied earlier on + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + $repl = $this->_makeGSUBinputMatch($inputGlyphs, $ignore); + $subs = $this->_makeGSUBinputReplacement(count($inputGlyphs), $substitute, $ignore, 0, count($inputGlyphs), 0); + $volt[] = ['match' => $repl, 'replace' => $subs, 'tag' => $tag, 'key' => $inputGlyphs[0], 'type' => 4, 'CompCount' => $Lookup[$i]['Subtable'][$c]['subs'][$s]['CompCount'], 'Lig' => $substitute]; + } + } // LookupType 5: Chaining Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 5) { + // Format 1: Context Substitution + if ($SubstFormat == 1) { + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['SubRuleSetCount']; $s++) { + // SubRuleSet + $subRule = []; + foreach ($Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['SubRule'] as $rule) { + // SubRule + $inputGlyphs = []; + if ($rule['GlyphCount'] > 1) { + $inputGlyphs = $rule['InputGlyphs']; + } + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['SubRuleSet'][$s]['FirstGlyph']; + ksort($inputGlyphs); + $nInput = count($inputGlyphs); + + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => '', 'match' => $contextInputMatch, 'nBacktrack' => 0, 'nInput' => $nInput, 'nLookahead' => 0, 'rules' => [],]; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $rule['SubstLookupRecord'][$b]['SequenceIndex']; + + // $Lookup[$lup] = secondary Lookup + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (count($Lookup[$lup]['Subtable'][$lus]['subs'])) { + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + $mLen = count($lookupGlyphs); + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + $REPL = implode(" ", $luss['substitute']); + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + } + + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } // Format 2: Class-based Context Glyph Substitution + elseif ($SubstFormat == 2) { + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + foreach ($Lookup[$i]['Subtable'][$c]['SubClassSet'] as $inputClass => $cscs) { + for ($cscrule = 0; $cscrule < $cscs['SubClassRuleCnt']; $cscrule++) { + $rule = $cscs['SubClassRule'][$cscrule]; + + $inputGlyphs = []; + + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + if ($rule['InputGlyphCount'] > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $rule['InputGlyphCount']; $gcl++) { + $classindex = $rule['Input'][$gcl]; + if (isset($Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex])) { + $inputGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex]; + } // if class[0] = all glyphs excluding those specified in all other classes + // set to blank '' for now + else { + $inputGlyphs[$gcl] = ''; + } + } + } + + $nInput = $rule['InputGlyphCount']; + $nIsubs = (2 * $nInput) - 1; + + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => '', 'match' => $contextInputMatch, 'nBacktrack' => 0, 'nInput' => $nInput, 'nLookahead' => 0, 'rules' => [],]; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // $Lookup[$lup] = secondary Lookup + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (isset($Lookup[$lup]['Subtable'][$lus]['subs']) && count($Lookup[$lup]['Subtable'][$lus]['subs'])) { + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + $mLen = count($lookupGlyphs); + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex); + $REPL = implode(" ", $luss['substitute']); + // Returns e.g. "REPL\${6}\${8}" or "\${1}\${2} \${3} REPL\${4}\${6}\${8} \${9}" + + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + + } // Format 3: Coverage-based Context Glyph Substitution p259 + elseif ($SubstFormat == 3) { + + // IgnoreMarks flag set on main Lookup table + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs']; + $CoverageInputGlyphs = implode('|', $inputGlyphs); + $nInput = $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; + + if ($Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']) { + $backtrackGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageBacktrackGlyphs']; + } else { + $backtrackGlyphs = []; + } + + // Returns e.g. ¦(FEEB|FEEC)(ignore) ¦(FD12|FD13)(ignore) ¦ + $backtrackMatch = $this->_makeGSUBbacktrackMatch($backtrackGlyphs, $ignore); + + if ($Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']) { + $lookaheadGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageLookaheadGlyphs']; + } else { + $lookaheadGlyphs = []; + } + + // Returns e.g. ¦(ignore) (FD12|FD13)¦(ignore) (FEEB|FEEC)¦ + $lookaheadMatch = $this->_makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore); + + $nBsubs = 2 * count($backtrackGlyphs); + $nIsubs = (2 * $nInput) - 1; + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => $backtrackMatch, 'match' => ($contextInputMatch . $lookaheadMatch), 'nBacktrack' => count($backtrackGlyphs), 'nInput' => $nInput, 'nLookahead' => count($lookaheadGlyphs), 'rules' => [],]; + + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $lup = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex']; + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (count($Lookup[$lup]['Subtable'][$lus]['subs'])) { + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + $mLen = count($lookupGlyphs); + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex); + $REPL = implode(" ", $luss['substitute']); + + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + + } // LookupType 6: ing Contextual Substitution Subtable + elseif ($Lookup[$i]['Type'] == 6) { + + // Format 1: Simple Chaining Context Glyph Substitution p255 + if ($SubstFormat == 1) { + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + for ($s = 0; $s < $Lookup[$i]['Subtable'][$c]['ChainSubRuleSetCount']; $s++) { + + // ChainSubRuleSet + $subRule = []; + $firstInputGlyph = $Lookup[$i]['Subtable'][$c]['CoverageGlyphs'][$s]; // First input gyyph + + foreach ($Lookup[$i]['Subtable'][$c]['ChainSubRuleSet'][$s]['ChainSubRule'] as $rule) { + // ChainSubRule + $inputGlyphs = []; + if ($rule['InputGlyphCount'] > 1) { + $inputGlyphs = $rule['InputGlyphs']; + } + $inputGlyphs[0] = $firstInputGlyph; + ksort($inputGlyphs); + $nInput = count($inputGlyphs); + + if ($rule['BacktrackGlyphCount']) { + $backtrackGlyphs = $rule['BacktrackGlyphs']; + } else { + $backtrackGlyphs = []; + } + $backtrackMatch = $this->_makeGSUBbacktrackMatch($backtrackGlyphs, $ignore); + + if ($rule['LookaheadGlyphCount']) { + $lookaheadGlyphs = $rule['LookaheadGlyphs']; + } else { + $lookaheadGlyphs = []; + } + + $lookaheadMatch = $this->_makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore); + + $nBsubs = 2 * count($backtrackGlyphs); + $nIsubs = (2 * $nInput) - 1; + + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => $backtrackMatch, 'match' => ($contextInputMatch . $lookaheadMatch), 'nBacktrack' => count($backtrackGlyphs), 'nInput' => $nInput, 'nLookahead' => count($lookaheadGlyphs), 'rules' => [],]; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // $Lookup[$lup] = secondary Lookup + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (count($Lookup[$lup]['Subtable'][$lus]['subs'])) { + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + $mLen = count($lookupGlyphs); + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex); + + $REPL = implode(" ", $luss['substitute']); + + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + } + + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + + } // Format 2: Class-based Chaining Context Glyph Substitution p257 + elseif ($SubstFormat == 2) { + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + foreach ($Lookup[$i]['Subtable'][$c]['ChainSubClassSet'] as $inputClass => $cscs) { + for ($cscrule = 0; $cscrule < $cscs['ChainSubClassRuleCnt']; $cscrule++) { + $rule = $cscs['ChainSubClassRule'][$cscrule]; + + // These contain classes of glyphs as strings + // $Lookup[$i]['Subtable'][$c]['InputClasses'][(class)] e.g. 02E6|02E7|02E8 + // $Lookup[$i]['Subtable'][$c]['LookaheadClasses'][(class)] + // $Lookup[$i]['Subtable'][$c]['BacktrackClasses'][(class)] + // These contain arrays of classIndexes + // [Backtrack] [Lookahead] and [Input] (Input is from the second position only) + + $inputGlyphs = []; + + if (isset($Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass])) { + $inputGlyphs[0] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$inputClass]; + } else { + $inputGlyphs[0] = ''; + } + if ($rule['InputGlyphCount'] > 1) { + // NB starts at 1 + for ($gcl = 1; $gcl < $rule['InputGlyphCount']; $gcl++) { + $classindex = $rule['Input'][$gcl]; + if (isset($Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex])) { + $inputGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['InputClasses'][$classindex]; + } // if class[0] = all glyphs excluding those specified in all other classes + // set to blank '' for now + else { + $inputGlyphs[$gcl] = ''; + } + } + } + + $nInput = $rule['InputGlyphCount']; + + if ($rule['BacktrackGlyphCount']) { + for ($gcl = 0; $gcl < $rule['BacktrackGlyphCount']; $gcl++) { + $classindex = $rule['Backtrack'][$gcl]; + if (isset($Lookup[$i]['Subtable'][$c]['BacktrackClasses'][$classindex])) { + $backtrackGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['BacktrackClasses'][$classindex]; + } // if class[0] = all glyphs excluding those specified in all other classes + // set to blank '' for now + else { + $backtrackGlyphs[$gcl] = ''; + } + } + } else { + $backtrackGlyphs = []; + } + // Returns e.g. ¦(FEEB|FEEC)(ignore) ¦(FD12|FD13)(ignore) ¦ + $backtrackMatch = $this->_makeGSUBbacktrackMatch($backtrackGlyphs, $ignore); + + if ($rule['LookaheadGlyphCount']) { + for ($gcl = 0; $gcl < $rule['LookaheadGlyphCount']; $gcl++) { + $classindex = $rule['Lookahead'][$gcl]; + if (isset($Lookup[$i]['Subtable'][$c]['LookaheadClasses'][$classindex])) { + $lookaheadGlyphs[$gcl] = $Lookup[$i]['Subtable'][$c]['LookaheadClasses'][$classindex]; + } // if class[0] = all glyphs excluding those specified in all other classes + // set to blank '' for now + else { + $lookaheadGlyphs[$gcl] = ''; + } + } + } else { + $lookaheadGlyphs = []; + } + // Returns e.g. ¦(ignore) (FD12|FD13)¦(ignore) (FEEB|FEEC)¦ + $lookaheadMatch = $this->_makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore); + + $nBsubs = 2 * count($backtrackGlyphs); + $nIsubs = (2 * $nInput) - 1; + + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => $backtrackMatch, 'match' => ($contextInputMatch . $lookaheadMatch), 'nBacktrack' => count($backtrackGlyphs), 'nInput' => $nInput, 'nLookahead' => count($lookaheadGlyphs), 'rules' => [],]; + + for ($b = 0; $b < $rule['SubstCount']; $b++) { + $lup = $rule['LookupListIndex'][$b]; + $seqIndex = $rule['SequenceIndex'][$b]; + + // $Lookup[$lup] = secondary Lookup + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (count($Lookup[$lup]['Subtable'][$lus]['subs'])) { + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + $mLen = count($lookupGlyphs); + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex); + $REPL = implode(" ", $luss['substitute']); + // Returns e.g. "REPL\${6}\${8}" or "\${1}\${2} \${3} REPL\${4}\${6}\${8} \${9}" + + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + + } // Format 3: Coverage-based Chaining Context Glyph Substitution p259 + elseif ($SubstFormat == 3) { + // IgnoreMarks flag set on main Lookup table + $ignore = $this->_getGSUBignoreString($Lookup[$i]['Flag'], $Lookup[$i]['MarkFilteringSet']); + $inputGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageInputGlyphs']; + $CoverageInputGlyphs = implode('|', $inputGlyphs); + $nInput = $Lookup[$i]['Subtable'][$c]['InputGlyphCount']; + + if ($Lookup[$i]['Subtable'][$c]['BacktrackGlyphCount']) { + $backtrackGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageBacktrackGlyphs']; + } else { + $backtrackGlyphs = []; + } + // Returns e.g. ¦(FEEB|FEEC)(ignore) ¦(FD12|FD13)(ignore) ¦ + $backtrackMatch = $this->_makeGSUBbacktrackMatch($backtrackGlyphs, $ignore); + + if ($Lookup[$i]['Subtable'][$c]['LookaheadGlyphCount']) { + $lookaheadGlyphs = $Lookup[$i]['Subtable'][$c]['CoverageLookaheadGlyphs']; + } else { + $lookaheadGlyphs = []; + } + // Returns e.g. ¦(ignore) (FD12|FD13)¦(ignore) (FEEB|FEEC)¦ + $lookaheadMatch = $this->_makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore); + + $nBsubs = 2 * count($backtrackGlyphs); + $nIsubs = (2 * $nInput) - 1; + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, [], 0); + $subRule = ['context' => 1, 'tag' => $tag, 'matchback' => $backtrackMatch, 'match' => ($contextInputMatch . $lookaheadMatch), 'nBacktrack' => count($backtrackGlyphs), 'nInput' => $nInput, 'nLookahead' => count($lookaheadGlyphs), 'rules' => [],]; + + for ($b = 0; $b < $Lookup[$i]['Subtable'][$c]['SubstCount']; $b++) { + $lup = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['LookupListIndex']; + $seqIndex = $Lookup[$i]['Subtable'][$c]['SubstLookupRecord'][$b]['SequenceIndex']; + for ($lus = 0; $lus < $Lookup[$lup]['SubtableCount']; $lus++) { + if (empty($Lookup[$lup]['Subtable'][$lus]['subs']) || ! is_array($Lookup[$lup]['Subtable'][$lus]['subs'])) { + continue; + } + + foreach ($Lookup[$lup]['Subtable'][$lus]['subs'] as $luss) { + $lookupGlyphs = $luss['Replace']; + + // Only apply if the (first) 'Replace' glyph from the + // Lookup list is in the [inputGlyphs] at ['SequenceIndex'] + // then apply the substitution + if (strpos($inputGlyphs[$seqIndex], $lookupGlyphs[0]) === false) { + continue; + } + + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + $contextInputMatch = $this->_makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex); + $REPL = implode(" ", $luss['substitute']); + + if (strpos("isol fina fin2 fin3 medi med2 init ", $tag) !== false && $scripttag == 'arab') { + $volt[] = ['match' => $lookupGlyphs[0], 'replace' => $REPL, 'tag' => $tag, 'prel' => $backtrackGlyphs, 'postl' => $lookaheadGlyphs, 'ignore' => $ignore]; + } else { + $subRule['rules'][] = ['type' => $Lookup[$lup]['Type'], 'match' => $lookupGlyphs, 'replace' => $luss['substitute'], 'seqIndex' => $seqIndex, 'key' => $lookupGlyphs[0],]; + } + } + } + } + if (count($subRule['rules'])) { + $volt[] = $subRule; + } + } + } + } + } + + return $volt; + } + + function _checkGSUBignore($flag, $glyph, $MarkFilteringSet) + { + $ignore = false; + // Flag & 0x0008 = Ignore Marks - (unless already done with MarkAttachmentType) + if ((($flag & 0x0008) == 0x0008 && ($flag & 0xFF00) == 0) && strpos($this->GlyphClassMarks, $glyph)) { + $ignore = true; + } + if ((($flag & 0x0004) == 0x0004) && strpos($this->GlyphClassLigatures, $glyph)) { + $ignore = true; + } + if ((($flag & 0x0002) == 0x0002) && strpos($this->GlyphClassBases, $glyph)) { + $ignore = true; + } + // Flag & 0xFF?? = MarkAttachmentType + if ($flag & 0xFF00) { + // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" + // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table + if (strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) { + $ignore = true; + } + } + // Flag & 0x0010 = UseMarkFilteringSet + if (($flag & 0x0010) && strpos($this->MarkGlyphSets[$MarkFilteringSet], $glyph)) { + $ignore = true; + } + + return $ignore; + } + + function _getGSUBignoreString($flag, $MarkFilteringSet) + { + // If ignoreFlag set, combine all ignore glyphs into -> "((?:(?: FBA1| FBA2| FBA3))*)" + // else "()" + // for Input - set on secondary Lookup table if in Context, and set Backtrack and Lookahead on Context Lookup + $str = ""; + $ignoreflag = 0; + + // Flag & 0xFF?? = MarkAttachmentType + if ($flag & 0xFF00) { + // "a lookup must ignore any mark glyphs that are not in the specified mark attachment class" + // $this->MarkAttachmentType is already adjusted for this i.e. contains all Marks except those in the MarkAttachmentClassDef table + $MarkAttachmentType = $flag >> 8; + $ignoreflag = $flag; + $str = $this->MarkAttachmentType[$MarkAttachmentType]; + } + + // Flag & 0x0010 = UseMarkFilteringSet + if ($flag & 0x0010) { + throw new \Mpdf\Exception\FontException("Font \"" . $this->fontkey . "\" contains MarkGlyphSets which is not supported"); + $str = $this->MarkGlyphSets[$MarkFilteringSet]; + } + + // If Ignore Marks set, supercedes any above + // Flag & 0x0008 = Ignore Marks - (unless already done with MarkAttachmentType) + if (($flag & 0x0008) == 0x0008 && ($flag & 0xFF00) == 0) { + $ignoreflag = 8; + $str = $this->GlyphClassMarks; + } + + // Flag & 0x0004 = Ignore Ligatures + if (($flag & 0x0004) == 0x0004) { + $ignoreflag += 4; + if ($str) { + $str .= "|"; + } + $str .= $this->GlyphClassLigatures; + } + // Flag & 0x0002 = Ignore BaseGlyphs + if (($flag & 0x0002) == 0x0002) { + $ignoreflag += 2; + if ($str) { + $str .= "|"; + } + $str .= $this->GlyphClassBases; + } + if ($str) { + // This originally returned e.g. ((?:(?:[IGNORE8]))*) when NOT specific to a Lookup e.g. rtlSub in + // arabictypesetting.GSUB.arab.DFLT.php + // This would save repeatedly saving long text strings if used multiple times + // When writing e.g. arabictypesetting.GSUB.arab.DFLT.php to file, included as $ignore[8] + // Would need to also write the $ignore array to that file + // // If UseMarkFilteringSet (specific to the Lookup) return the string + // if (($flag & 0x0010) && ($flag & 0x0008) != 0x0008) { + // return "((?:(?:" . $str . "))*)"; + // } + // else { return "((?:(?:" . "[IGNORE".$ignoreflag."]" . "))*)"; } + // // e.g. ((?:(?: 0031| 0032| 0033| 0034| 0045))*) + // But never finished coding it to add the $ignore array to the file, and it doesn't seem to occur often enough to be worth + // writing. So just output it as a string: + return "((?:(?:" . $str . "))*)"; + } else { + return "()"; + } + } + + // GSUB Patterns + + /* + BACKTRACK INPUT LOOKAHEAD + ================================== ================== ================================== + (FEEB|FEEC)(ign) ¦(FD12|FD13)(ign) ¦(0612)¦(ign) (0613)¦(ign) (FD12|FD13)¦(ign) (FEEB|FEEC) + ---------------- ---------------- ----- ------------ --------------- --------------- + Backtrack 1 Backtrack 2 Input 1 Input 2 Lookahead 1 Lookahead 2 + -------- --- --------- --- ---- --- ---- --- --------- --- ------- + \${1} \${2} \${3} \${4} \${5+} \${6+} \${7+} \${8+} + + nBacktrack = 2 nInput = 2 nLookahead = 2 + + nBsubs = 2xnBack nIsubs = (nBsubs+) nLsubs = (nBsubs+nIsubs+) 2xnLookahead + "\${1}\${2} " (nInput*2)-1 "\${5+} \${6+}" + "REPL" + + ¦\${1}\${2} ¦\${3}\${4} ¦REPL¦\${5+} \${6+}¦\${7+} \${8+}¦ + + + INPUT nInput = 5 + ============================================================ + ¦(0612)¦(ign) (0613)¦(ign) (0614)¦(ign) (0615)¦(ign) (0615)¦ + \${1} \${2} \${3} \${4} \${5} \${6} \${7} \${8} \${9} (All backreference numbers are + nBsubs) + ----- ------------ ------------ ------------ ------------ + Input 1 Input 2 Input 3 Input 4 Input 5 + + A====== SequenceIndex=1 ; Lookup match nGlyphs=1 + B=================== SequenceIndex=1 ; Lookup match nGlyphs=2 + C=============================== SequenceIndex=1 ; Lookup match nGlyphs=3 + D======================= SequenceIndex=2 ; Lookup match nGlyphs=2 + E===================================== SequenceIndex=2 ; Lookup match nGlyphs=3 + F====================== SequenceIndex=4 ; Lookup match nGlyphs=2 + + All backreference numbers are + nBsubs + A - "REPL\${2} \${3}\${4} \${5}\${6} \${7}\${8} \${9}" + B - "REPL\${2}\${4} \${5}\${6} \${7}\${8} \${9}" + C - "REPL\${2}\${4}\${6} \${7}\${8} \${9}" + D - "\${1} REPL\${2}\${4}\${6} \${7}\${8} \${9}" + E - "\${1} REPL\${2}\${4}\${6}\${8} \${9}" + F - "\${1}\${2} \${3}\${4} \${5} REPL\${6}\${8}" + */ + + function _makeGSUBcontextInputMatch($inputGlyphs, $ignore, $lookupGlyphs, $seqIndex) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + // $inputGlyphs = array of glyphs(glyphstrings) making up Input sequence in Context + // $lookupGlyphs = array of glyphs (single Glyphs) making up Lookup Input sequence + $mLen = count($lookupGlyphs); // nGlyphs in the secondary Lookup match + $nInput = count($inputGlyphs); // nGlyphs in the Primary Input sequence + $str = ""; + for ($i = 0; $i < $nInput; $i++) { + if ($i > 0) { + $str .= $ignore . " "; + } + if ($i >= $seqIndex && $i < ($seqIndex + $mLen)) { + $str .= "(" . $lookupGlyphs[($i - $seqIndex)] . ")"; + } else { + $str .= "(" . $inputGlyphs[($i)] . ")"; + } + } + + return $str; + } + + function _makeGSUBinputMatch($inputGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(0612)¦(ignore) (0613)¦(ignore) (0614)¦ + // $inputGlyphs = array of glyphs(glyphstrings) making up Input sequence in Context + // $lookupGlyphs = array of glyphs making up Lookup Input sequence - if applicable + $str = ""; + for ($i = 1; $i <= count($inputGlyphs); $i++) { + if ($i > 1) { + $str .= $ignore . " "; + } + $str .= "(" . $inputGlyphs[($i - 1)] . ")"; + } + + return $str; + } + + function _makeGSUBbacktrackMatch($backtrackGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(FEEB|FEEC)(ignore) ¦(FD12|FD13)(ignore) ¦ + // $backtrackGlyphs = array of glyphstrings making up Backtrack sequence + // 3 2 1 0 + // each item being e.g. E0AD|E0AF|F1FD + $str = ""; + for ($i = (count($backtrackGlyphs) - 1); $i >= 0; $i--) { + $str .= "(" . $backtrackGlyphs[$i] . ")" . $ignore . " "; + } + + return $str; + } + + function _makeGSUBlookaheadMatch($lookaheadGlyphs, $ignore) + { + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // Returns e.g. ¦(ignore) (FD12|FD13)¦(ignore) (FEEB|FEEC)¦ + // $lookaheadGlyphs = array of glyphstrings making up Lookahead sequence + // 0 1 2 3 + // each item being e.g. E0AD|E0AF|F1FD + $str = ""; + for ($i = 0; $i < count($lookaheadGlyphs); $i++) { + $str .= $ignore . " (" . $lookaheadGlyphs[$i] . ")"; + } + + return $str; + } + + function _makeGSUBinputReplacement($nInput, $REPL, $ignore, $nBsubs, $mLen, $seqIndex) + { + // Returns e.g. "REPL\${6}\${8}" or "\${1}\${2} \${3} REPL\${4}\${6}\${8} \${9}" + // $nInput nGlyphs in the Primary Input sequence + // $REPL replacement glyphs from secondary lookup + // $ignore = "((?:(?: FBA1| FBA2| FBA3))*)" or "()" + // $nBsubs Number of Backtrack substitutions (= 2x Number of Backtrack glyphs) + // $mLen nGlyphs in the secondary Lookup match - if no secondary lookup, should=$nInput + // $seqIndex Sequence Index to apply the secondary match + if ($ignore == "()") { + $ign = false; + } else { + $ign = true; + } + $str = ""; + if ($nInput == 1) { + $str = $REPL; + } elseif ($nInput > 1) { + if ($mLen == $nInput) { // whole string replaced + $str = $REPL; + if ($ign) { + // for every nInput over 1, add another replacement backreference, to move IGNORES after replacement + for ($x = 2; $x <= $nInput; $x++) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + } + } else { // if only part of string replaced: + for ($x = 1; $x < ($seqIndex + 1); $x++) { + if ($x == 1) { + $str .= '\\' . ($nBsubs + 1); + } else { + if ($ign) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1))); + } + } + if ($seqIndex > 0) { + $str .= " "; + } + $str .= $REPL; + if ($ign) { + for ($x = (max(($seqIndex + 1), 2)); $x < ($seqIndex + 1 + $mLen); $x++) { // move IGNORES after replacement + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + } + for ($x = ($seqIndex + 1 + $mLen); $x <= $nInput; $x++) { + if ($ign) { + $str .= '\\' . ($nBsubs + (2 * ($x - 1))); + } + $str .= ' \\' . ($nBsubs + 1 + (2 * ($x - 1))); + } + } + } + + return $str; + } + + function _getCoverage($convert2hex = true, $mode = 1) + { + $g = []; + $ctr = 0; + $CoverageFormat = $this->read_ushort(); + if ($CoverageFormat == 1) { + $CoverageGlyphCount = $this->read_ushort(); + for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) { + $glyphID = $this->read_ushort(); + $uni = $this->glyphToChar[$glyphID][0]; + if ($convert2hex) { + $g[] = unicode_hex($uni); + } elseif ($mode == 2) { + $g[$uni] = $ctr; + $ctr++; + } else { + $g[] = $glyphID; + } + } + } + if ($CoverageFormat == 2) { + $RangeCount = $this->read_ushort(); + for ($r = 0; $r < $RangeCount; $r++) { + $start = $this->read_ushort(); + $end = $this->read_ushort(); + $StartCoverageIndex = $this->read_ushort(); // n/a + for ($glyphID = $start; $glyphID <= $end; $glyphID++) { + $uni = $this->glyphToChar[$glyphID][0]; + if ($convert2hex) { + $g[] = unicode_hex($uni); + } elseif ($mode == 2) { + $uni = $g[$uni] = $ctr; + $ctr++; + } else { + $g[] = $glyphID; + } + } + } + } + + return $g; + } + + function _getClasses($offset) + { + $this->seek($offset); + $ClassFormat = $this->read_ushort(); + $GlyphByClass = []; + if ($ClassFormat == 1) { + $StartGlyph = $this->read_ushort(); + $GlyphCount = $this->read_ushort(); + for ($i = 0; $i < $GlyphCount; $i++) { + $startGlyphID = $StartGlyph + $i; + $endGlyphID = $StartGlyph + $i; + $class = $this->read_ushort(); + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if (isset($this->glyphToChar[$g][0])) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]); + } + } + } + } elseif ($ClassFormat == 2) { + $tableCount = $this->read_ushort(); + for ($i = 0; $i < $tableCount; $i++) { + $startGlyphID = $this->read_ushort(); + $endGlyphID = $this->read_ushort(); + $class = $this->read_ushort(); + for ($g = $startGlyphID; $g <= $endGlyphID; $g++) { + if ($this->glyphToChar[$g][0]) { + $GlyphByClass[$class][] = unicode_hex($this->glyphToChar[$g][0]); + } + } + } + } + $gbc = []; + foreach ($GlyphByClass as $class => $garr) { + $gbc[$class] = implode('|', $garr); + } + + return $gbc; + } + + function _getGPOStables() + { + /////////////////////////////////// + // GPOS - Glyph Positioning + /////////////////////////////////// + if (!isset($this->tables["GPOS"])) { + return [[], [], []]; + } + + $ffeats = []; + $gpos_offset = $this->seek_table("GPOS"); + $this->skip(4); + $ScriptList_offset = $gpos_offset + $this->read_ushort(); + $FeatureList_offset = $gpos_offset + $this->read_ushort(); + $LookupList_offset = $gpos_offset + $this->read_ushort(); + + // ScriptList + $this->seek($ScriptList_offset); + $ScriptCount = $this->read_ushort(); + for ($i = 0; $i < $ScriptCount; $i++) { + $ScriptTag = $this->read_tag(); // = "beng", "deva" etc. + $ScriptTableOffset = $this->read_ushort(); + $ffeats[$ScriptTag] = $ScriptList_offset + $ScriptTableOffset; + } + + // Script Table + foreach ($ffeats as $t => $o) { + $ls = []; + $this->seek($o); + $DefLangSys_offset = $this->read_ushort(); + if ($DefLangSys_offset > 0) { + $ls['DFLT'] = $DefLangSys_offset + $o; + } + $LangSysCount = $this->read_ushort(); + for ($i = 0; $i < $LangSysCount; $i++) { + $LangTag = $this->read_tag(); // = + $LangTableOffset = $this->read_ushort(); + $ls[$LangTag] = $o + $LangTableOffset; + } + $ffeats[$t] = $ls; + } + + // Get FeatureIndexList + // LangSys Table - from first listed langsys + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = []; + $langsystable_offset = $o; + $this->seek($langsystable_offset); + $LookUpOrder = $this->read_ushort(); //==NULL + $ReqFeatureIndex = $this->read_ushort(); + if ($ReqFeatureIndex != 0xFFFF) { + $FeatureIndex[] = $ReqFeatureIndex; + } + $FeatureCount = $this->read_ushort(); + for ($i = 0; $i < $FeatureCount; $i++) { + $FeatureIndex[] = $this->read_ushort(); // = index of feature + } + $ffeats[$st][$t] = $FeatureIndex; + } + } + // Feauture List => LookupListIndex es + $this->seek($FeatureList_offset); + $FeatureCount = $this->read_ushort(); + $Feature = []; + for ($i = 0; $i < $FeatureCount; $i++) { + $tag = $this->read_tag(); + if ($tag === 'kern') { + $this->haskernGPOS = true; + } + $Feature[$i] = ['tag' => $tag]; + $Feature[$i]['offset'] = $FeatureList_offset + $this->read_ushort(); + } + + for ($i = 0; $i < $FeatureCount; $i++) { + $this->seek($Feature[$i]['offset']); + $this->read_ushort(); // null + $Feature[$i]['LookupCount'] = $Lookupcount = $this->read_ushort(); + $Feature[$i]['LookupListIndex'] = []; + for ($c = 0; $c < $Lookupcount; $c++) { + $Feature[$i]['LookupListIndex'][] = $this->read_ushort(); + } + } + + foreach ($ffeats as $st => $scripts) { + foreach ($scripts as $t => $o) { + $FeatureIndex = $ffeats[$st][$t]; + foreach ($FeatureIndex as $k => $fi) { + $ffeats[$st][$t][$k] = $Feature[$fi]; + } + } + } + + $gpos = []; + $GPOSScriptLang = []; + foreach ($ffeats as $st => $scripts) { + + foreach ($scripts as $t => $langsys) { + + $lg = []; + foreach ($langsys as $ft) { + $lg[$ft['LookupListIndex'][0]] = $ft; + } + + // list of Lookups in order they need to be run i.e. order listed in Lookup table + ksort($lg); + foreach ($lg as $ft) { + $gpos[$st][$t][$ft['tag']] = $ft['LookupListIndex']; + } + if (!isset($GPOSScriptLang[$st])) { + $GPOSScriptLang[$st] = ''; + } + $GPOSScriptLang[$st] .= $t . ' '; + } + } + + // Get metadata and offsets for whole Lookup List table + $this->seek($LookupList_offset); + $LookupCount = $this->read_ushort(); + $Lookup = []; + $Offsets = []; + $SubtableCount = []; + + for ($i = 0; $i < $LookupCount; $i++) { + $Offsets[$i] = $LookupList_offset + $this->read_ushort(); + } + + for ($i = 0; $i < $LookupCount; $i++) { + $this->seek($Offsets[$i]); + $Lookup[$i]['Type'] = $this->read_ushort(); + $Lookup[$i]['Flag'] = $flag = $this->read_ushort(); + $Lookup[$i]['SubtableCount'] = $SubtableCount[$i] = $this->read_ushort(); + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $Lookup[$i]['Subtables'][$c] = $Offsets[$i] + $this->read_ushort(); + } + // MarkFilteringSet = Index (base 0) into GDEF mark glyph sets structure + if (($flag & 0x0010) === 0x0010) { + $Lookup[$i]['MarkFilteringSet'] = $this->read_ushort(); + } else { + $Lookup[$i]['MarkFilteringSet'] = ''; + } + + // Lookup Type 9: Extension + if ($Lookup[$i]['Type'] == 9) { + // Overwrites new offset (32-bit) for each subtable, and a new lookup Type + for ($c = 0; $c < $SubtableCount[$i]; $c++) { + $this->seek($Lookup[$i]['Subtables'][$c]); + $ExtensionPosFormat = $this->read_ushort(); + $type = $this->read_ushort(); + $Lookup[$i]['Subtables'][$c] = $Lookup[$i]['Subtables'][$c] + $this->read_ulong(); + } + $Lookup[$i]['Type'] = $type; + } + } + + // Process Whole LookupList - Get LuCoverage = Lookup coverage just for first glyph + $this->LuCoverage = []; + for ($i = 0; $i < $LookupCount; $i++) { + for ($c = 0; $c < $Lookup[$i]['SubtableCount']; $c++) { + $this->seek($Lookup[$i]['Subtables'][$c]); + $PosFormat = $this->read_ushort(); + + if ($Lookup[$i]['Type'] == 7 && $PosFormat == 3) { + $this->skip(4); + } elseif ($Lookup[$i]['Type'] == 8 && $PosFormat == 3) { + $BacktrackGlyphCount = $this->read_ushort(); + $this->skip(2 * $BacktrackGlyphCount + 2); + } + // NB Coverage only looks at glyphs for position 1 (i.e. 7.3 and 8.3) // NEEDS TO READ ALL ******************** + // NB For e.g. Type 4, this may be the Coverage for the Mark + $Coverage = $Lookup[$i]['Subtables'][$c] + $this->read_ushort(); + $this->seek($Coverage); + $glyphs = $this->_getCoverage(false, 2); + $this->LuCoverage[$i][$c] = $glyphs; + } + } + + $this->fontCache->jsonWrite($this->fontkey . '.GPOSdata.json', $this->LuCoverage); + + return [$GPOSScriptLang, $gpos, $Lookup]; + } + + function makeSubset($file, &$subset, $TTCfontID = 0, $debug = false, $useOTL = false) + { + $this->useOTL = $useOTL; + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file %s', $file)); + } + + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->ascent = 0; + $this->descent = 0; + $this->strikeoutSize = 0; + $this->strikeoutPosition = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->skip(4); + $this->maxUni = 0; + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000], true)) { + throw new \Mpdf\Exception\FontException(sprintf('Error parsing TrueType Collection: version=%s - %s', $version, $file)); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + $this->readTableDirectory($debug); + + // head - Font header table + $this->seek_table('head'); + $this->skip(50); + $indexToLocFormat = $this->read_ushort(); + $glyphDataFormat = $this->read_ushort(); + + // hhea - Horizontal header table + $this->seek_table('hhea'); + $this->skip(32); + $metricDataFormat = $this->read_ushort(); + $orignHmetrics = $numberOfHMetrics = $this->read_ushort(); + + // maxp - Maximum profile table + $this->seek_table('maxp'); + $this->skip(4); + $numGlyphs = $this->read_ushort(); + + // cmap - Character to glyph index mapping table + $cmap_offset = $this->seek_table('cmap'); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have Unicode cmap (platform 3, encoding 1, format 4, or platform 0 [any encoding] format 4)', $this->filename)); + } + + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + + // Map Unmapped glyphs - from $numGlyphs + if ($useOTL) { + $bctr = 0xE000; + for ($gid = 1; $gid < $numGlyphs; $gid++) { + if (!isset($glyphToChar[$gid])) { + while (isset($charToGlyph[$bctr])) { + $bctr++; + } // Avoid overwriting a glyph already mapped in PUA + if ($bctr > 0xF8FF) { + throw new \Mpdf\Exception\FontException($file . " : WARNING - Font cannot map all included glyphs into Private Use Area U+E000 - U+F8FF; cannot use useOTL on this font"); + } + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $bctr++; + } + } + } + + $this->charToGlyph = $charToGlyph; + $this->glyphToChar = $glyphToChar; + + // hmtx - Horizontal metrics table + $scale = 1; // not used + $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale); + + // loca - Index to location + $this->getLOCA($indexToLocFormat, $numGlyphs); + + $subsetglyphs = [0 => 0, 1 => 1, 2 => 2]; + $subsetCharToGlyph = []; + foreach ($subset as $code) { + if (isset($this->charToGlyph[$code])) { + $subsetglyphs[$this->charToGlyph[$code]] = $code; // Old Glyph ID => Unicode + $subsetCharToGlyph[$code] = $this->charToGlyph[$code]; // Unicode to old GlyphID + } + $this->maxUni = max($this->maxUni, $code); + } + + list($start, $dummy) = $this->get_table_pos('glyf'); + + $glyphSet = []; + ksort($subsetglyphs); + $n = 0; + $fsLastCharIndex = 0; // maximum Unicode index (character code) in this font, according to the cmap subtable for platform ID 3 and platform- specific encoding ID 0 or 1. + foreach ($subsetglyphs as $originalGlyphIdx => $uni) { + $fsLastCharIndex = max($fsLastCharIndex, $uni); + $glyphSet[$originalGlyphIdx] = $n; // old glyphID to new glyphID + $n++; + } + + $codeToGlyph = []; + ksort($subsetCharToGlyph); + foreach ($subsetCharToGlyph as $uni => $originalGlyphIdx) { + $codeToGlyph[$uni] = $glyphSet[$originalGlyphIdx]; + } + $this->codeToGlyph = $codeToGlyph; + + ksort($subsetglyphs); + foreach ($subsetglyphs as $originalGlyphIdx => $uni) { + $this->getGlyphs($originalGlyphIdx, $start, $glyphSet, $subsetglyphs); + } + + $numGlyphs = $numberOfHMetrics = count($subsetglyphs); + + // name - table copied from the original + // MS spec says that "Platform and encoding ID's in the name table should be consistent with those in the cmap table. + // If they are not, the font will not load in Windows" + // Doesn't seem to be a problem? + $this->add('name', $this->get_table('name')); + + // tables copied from the original + $tags = ['cvt ', 'fpgm', 'prep', 'gasp']; + foreach ($tags as $tag) { + if (isset($this->tables[$tag])) { + $this->add($tag, $this->get_table($tag)); + } + } + + // post - PostScript + if (isset($this->tables['post'])) { + $opost = $this->get_table('post'); + $post = "\x00\x03\x00\x00" . substr($opost, 4, 12) . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + $this->add('post', $post); + } + + // Sort CID2GID map into segments of contiguous codes + ksort($codeToGlyph); + unset($codeToGlyph[0]); + + $rangeid = 0; + $range = []; + $prevcid = -2; + $prevglidx = -1; + + // for each character + foreach ($codeToGlyph as $cid => $glidx) { + if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) { + $range[$rangeid][] = $glidx; + } else { + // new range + $rangeid = $cid; + $range[$rangeid] = []; + $range[$rangeid][] = $glidx; + } + $prevcid = $cid; + $prevglidx = $glidx; + } + + // cmap - Character to glyph mapping + $segCount = count($range) + 1; // + 1 Last segment has missing character 0xFFFF + $searchRange = 1; + $entrySelector = 0; + + while ($searchRange * 2 <= $segCount) { + $searchRange *= 2; + ++$entrySelector; + } + + $searchRange *= 2; + $rangeShift = $segCount * 2 - $searchRange; + $length = 16 + (8 * $segCount) + ($numGlyphs + 1); + $cmap = [ + 0, 3, // Index : version, number of encoding subtables + 0, 0, // Encoding Subtable : platform (UNI=0), encoding 0 + 0, 28, // Encoding Subtable : offset (hi,lo) + 0, 3, // Encoding Subtable : platform (UNI=0), encoding 3 + 0, 28, // Encoding Subtable : offset (hi,lo) + 3, 1, // Encoding Subtable : platform (MS=3), encoding 1 + 0, 28, // Encoding Subtable : offset (hi,lo) + 4, $length, 0, // Format 4 Mapping subtable: format, length, language + $segCount * 2, + $searchRange, + $entrySelector, + $rangeShift, + ]; + + // endCode(s) + foreach ($range as $start => $subrange) { + $endCode = $start + (count($subrange) - 1); + $cmap[] = $endCode; // endCode(s) + } + + $cmap[] = 0xFFFF; // endCode of last Segment + $cmap[] = 0; // reservedPad + + // startCode(s) + foreach ($range as $start => $subrange) { + $cmap[] = $start; // startCode(s) + } + + $cmap[] = 0xFFFF; // startCode of last Segment + + // idDelta(s) + foreach ($range as $start => $subrange) { + $idDelta = -($start - $subrange[0]); + $n += count($subrange); + $cmap[] = $idDelta; // idDelta(s) + } + + $cmap[] = 1; // idDelta of last Segment + // idRangeOffset(s) + + foreach ($range as $subrange) { + $cmap[] = 0; // idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0 + } + + $cmap[] = 0; // idRangeOffset of last Segment + foreach ($range as $subrange) { + foreach ($subrange as $glidx) { + $cmap[] = $glidx; + } + } + + $cmap[] = 0; // Mapping for last character + $cmapstr = ''; + + foreach ($cmap as $cm) { + $cmapstr .= pack('n', $cm); + } + $this->add('cmap', $cmapstr); + + // glyf - Glyph data + list($glyfOffset, $glyfLength) = $this->get_table_pos('glyf'); + if ($glyfLength < $this->maxStrLenRead) { + $glyphData = $this->get_table('glyf'); + } + + $offsets = []; + $glyf = ''; + $pos = 0; + $hmtxstr = ''; + $xMinT = 0; + $yMinT = 0; + $xMaxT = 0; + $yMaxT = 0; + $advanceWidthMax = 0; + $minLeftSideBearing = 0; + $minRightSideBearing = 0; + $xMaxExtent = 0; + $maxPoints = 0; // points in non-compound glyph + $maxContours = 0; // contours in non-compound glyph + $maxComponentPoints = 0; // points in compound glyph + $maxComponentContours = 0; // contours in compound glyph + $maxComponentElements = 0; // number of glyphs referenced at top level + $maxComponentDepth = 0; // levels of recursion, set to 0 if font has only simple glyphs + $this->glyphdata = []; + + foreach ($subsetglyphs as $originalGlyphIdx => $uni) { + // hmtx - Horizontal Metrics + $hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx); + $hmtxstr .= $hm; + + $offsets[] = $pos; + $glyphPos = $this->glyphPos[$originalGlyphIdx]; + $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos; + if ($glyfLength < $this->maxStrLenRead) { + $data = substr($glyphData, $glyphPos, $glyphLen); + } else { + if ($glyphLen > 0) { + $data = $this->get_chunk($glyfOffset + $glyphPos, $glyphLen); + } else { + $data = ''; + } + } + + if ($glyphLen > 0) { + if (_RECALC_PROFILE) { + $xMin = $this->unpack_short(substr($data, 2, 2)); + $yMin = $this->unpack_short(substr($data, 4, 2)); + $xMax = $this->unpack_short(substr($data, 6, 2)); + $yMax = $this->unpack_short(substr($data, 8, 2)); + $xMinT = min($xMinT, $xMin); + $yMinT = min($yMinT, $yMin); + $xMaxT = max($xMaxT, $xMax); + $yMaxT = max($yMaxT, $yMax); + $aw = $this->unpack_short(substr($hm, 0, 2)); + $lsb = $this->unpack_short(substr($hm, 2, 2)); + $advanceWidthMax = max($advanceWidthMax, $aw); + $minLeftSideBearing = min($minLeftSideBearing, $lsb); + $minRightSideBearing = min($minRightSideBearing, ($aw - $lsb - ($xMax - $xMin))); + $xMaxExtent = max($xMaxExtent, ($lsb + ($xMax - $xMin))); + } + $up = unpack("n", substr($data, 0, 2)); + } + if ($glyphLen > 2 && ($up[1] & (1 << 15))) { // If number of contours <= -1 i.e. composiste glyph + $pos_in_glyph = 10; + $flags = GlyphOperator::MORE; + $nComponentElements = 0; + while ($flags & GlyphOperator::MORE) { + $nComponentElements += 1; // number of glyphs referenced at top level + $up = unpack("n", substr($data, $pos_in_glyph, 2)); + $flags = $up[1]; + $up = unpack("n", substr($data, $pos_in_glyph + 2, 2)); + $glyphIdx = $up[1]; + $this->glyphdata[$originalGlyphIdx]['compGlyphs'][] = $glyphIdx; + $data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]); + $pos_in_glyph += 4; + if ($flags & GlyphOperator::WORDS) { + $pos_in_glyph += 4; + } else { + $pos_in_glyph += 2; + } + if ($flags & GlyphOperator::SCALE) { + $pos_in_glyph += 2; + } elseif ($flags & GlyphOperator::XYSCALE) { + $pos_in_glyph += 4; + } elseif ($flags & GlyphOperator::TWOBYTWO) { + $pos_in_glyph += 8; + } + } + $maxComponentElements = max($maxComponentElements, $nComponentElements); + + } // Simple Glyph + elseif (_RECALC_PROFILE && $glyphLen > 2 && $up[1] < (1 << 15) && $up[1] > 0) { // Number of contours > 0 simple glyph + $nContours = $up[1]; + $this->glyphdata[$originalGlyphIdx]['nContours'] = $nContours; + $maxContours = max($maxContours, $nContours); + + // Count number of points in simple glyph + $pos_in_glyph = 10 + ($nContours * 2) - 2; // Last endContourPoint + $up = unpack("n", substr($data, $pos_in_glyph, 2)); + $points = $up[1] + 1; + $this->glyphdata[$originalGlyphIdx]['nPoints'] = $points; + $maxPoints = max($maxPoints, $points); + } + + $glyf .= $data; + $pos += $glyphLen; + if ($pos % 4 != 0) { + $padding = 4 - ($pos % 4); + $glyf .= str_repeat("\0", $padding); + $pos += $padding; + } + } + + if (_RECALC_PROFILE) { + foreach ($this->glyphdata as $originalGlyphIdx => $val) { + $maxdepth = $depth = -1; + $points = 0; + $contours = 0; + $this->getGlyphData($originalGlyphIdx, $maxdepth, $depth, $points, $contours); + $maxComponentDepth = max($maxComponentDepth, $maxdepth); + $maxComponentPoints = max($maxComponentPoints, $points); + $maxComponentContours = max($maxComponentContours, $contours); + } + } + + $offsets[] = $pos; + $this->add('glyf', $glyf); + + // hmtx - Horizontal Metrics + $this->add('hmtx', $hmtxstr); + + // loca - Index to location + $locastr = ''; + if ((($pos + 1) >> 1) > 0xFFFF) { + $indexToLocFormat = 1; // long format + foreach ($offsets as $offset) { + $locastr .= pack("N", $offset); + } + } else { + $indexToLocFormat = 0; // short format + foreach ($offsets as $offset) { + $locastr .= pack("n", ($offset / 2)); + } + } + $this->add('loca', $locastr); + + // head - Font header + $head = $this->get_table('head'); + $head = $this->_set_ushort($head, 50, $indexToLocFormat); + + if (_RECALC_PROFILE) { + $head = $this->_set_short($head, 36, $xMinT); // for all glyph bounding boxes + $head = $this->_set_short($head, 38, $yMinT); // for all glyph bounding boxes + $head = $this->_set_short($head, 40, $xMaxT); // for all glyph bounding boxes + $head = $this->_set_short($head, 42, $yMaxT); // for all glyph bounding boxes + $head[17] = chr($head[17] & ~(1 << 4)); // Unset Bit 4 (as hdmx/LTSH tables not included) + } + + $this->add('head', $head); + + // hhea - Horizontal Header + $hhea = $this->get_table('hhea'); + $hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics); + if (_RECALC_PROFILE) { + $hhea = $this->_set_ushort($hhea, 10, $advanceWidthMax); + $hhea = $this->_set_short($hhea, 12, $minLeftSideBearing); + $hhea = $this->_set_short($hhea, 14, $minRightSideBearing); + $hhea = $this->_set_short($hhea, 16, $xMaxExtent); + } + $this->add('hhea', $hhea); + + // maxp - Maximum Profile + $maxp = $this->get_table('maxp'); + $maxp = $this->_set_ushort($maxp, 4, $numGlyphs); + if (_RECALC_PROFILE) { + $maxp = $this->_set_ushort($maxp, 6, $maxPoints); // points in non-compound glyph + $maxp = $this->_set_ushort($maxp, 8, $maxContours); // contours in non-compound glyph + $maxp = $this->_set_ushort($maxp, 10, $maxComponentPoints); // points in compound glyph + $maxp = $this->_set_ushort($maxp, 12, $maxComponentContours); // contours in compound glyph + $maxp = $this->_set_ushort($maxp, 28, $maxComponentElements); // number of glyphs referenced at top level + $maxp = $this->_set_ushort($maxp, 30, $maxComponentDepth); // levels of recursion, set to 0 if font has only simple glyphs + } + $this->add('maxp', $maxp); + + // OS/2 - OS/2 + if (isset($this->tables['OS/2'])) { + $os2_offset = $this->seek_table("OS/2"); + if (_RECALC_PROFILE) { + $fsSelection = $this->get_ushort($os2_offset + 62); + $fsSelection = ($fsSelection & ~(1 << 6)); // 2-byte bit field containing information concerning the nature of the font patterns + // bit#0 = Italic; bit#5=Bold + // Match name table's font subfamily string + // Clear bit#6 used for 'Regular' and optional + } + + // NB Currently this method never subsets characters above BMP + // Could set nonBMP bit according to $this->maxUni + $nonBMP = $this->get_ushort($os2_offset + 46); + $nonBMP = ($nonBMP & ~(1 << 9)); // Unset Bit 57 (indicates non-BMP) - for interactive forms + + $os2 = $this->get_table('OS/2'); + if (_RECALC_PROFILE) { + $os2 = $this->_set_ushort($os2, 62, $fsSelection); + $os2 = $this->_set_ushort($os2, 66, $fsLastCharIndex); + $os2 = $this->_set_ushort($os2, 42, 0x0000); // ulCharRange (ulUnicodeRange) bits 24-31 | 16-23 + $os2 = $this->_set_ushort($os2, 44, 0x0000); // ulCharRange (Unicode ranges) bits 8-15 | 0-7 + $os2 = $this->_set_ushort($os2, 46, $nonBMP); // ulCharRange (Unicode ranges) bits 56-63 | 48-55 + $os2 = $this->_set_ushort($os2, 48, 0x0000); // ulCharRange (Unicode ranges) bits 40-47 | 32-39 + $os2 = $this->_set_ushort($os2, 50, 0x0000); // ulCharRange (Unicode ranges) bits 88-95 | 80-87 + $os2 = $this->_set_ushort($os2, 52, 0x0000); // ulCharRange (Unicode ranges) bits 72-79 | 64-71 + $os2 = $this->_set_ushort($os2, 54, 0x0000); // ulCharRange (Unicode ranges) bits 120-127 | 112-119 + $os2 = $this->_set_ushort($os2, 56, 0x0000); // ulCharRange (Unicode ranges) bits 104-111 | 96-103 + } + $os2 = $this->_set_ushort($os2, 46, $nonBMP); // Unset Bit 57 (indicates non-BMP) - for interactive forms + + $this->add('OS/2', $os2); + } + + fclose($this->fh); + + // Put the TTF file together + $stm = ''; + $this->endTTFile($stm); + + return $stm; + } + + function makeSubsetSIP($file, &$subset, $TTCfontID = 0, $debug = false, $useOTL = 0) + { + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file "%s"', $file)); + } + + $this->filename = $file; + $this->_pos = 0; + $this->useOTL = $useOTL; // mPDF 5.7.1 + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->ascent = 0; + $this->descent = 0; + $this->strikeoutSize = 0; + $this->strikeoutPosition = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->skip(4); + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000])) { + throw new \Mpdf\Exception\FontException("ERROR - Error parsing TrueType Collection: version=" . $version . " - " . $file); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + $this->readTableDirectory($debug); + + // head - Font header table + $this->seek_table('head'); + $this->skip(50); + $indexToLocFormat = $this->read_ushort(); + $glyphDataFormat = $this->read_ushort(); + + // hhea - Horizontal header table + $this->seek_table('hhea'); + $this->skip(32); + $metricDataFormat = $this->read_ushort(); + $orignHmetrics = $numberOfHMetrics = $this->read_ushort(); + + // maxp - Maximum profile table + $this->seek_table('maxp'); + $this->skip(4); + $numGlyphs = $this->read_ushort(); + + // cmap - Character to glyph index mapping table + $cmap_offset = $this->seek_table('cmap'); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + + if (($platformID == 3 && $encodingID == 10) || $platformID == 0) { // Microsoft, Unicode Format 12 table HKCS + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 12) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + $unicode_cmap_offset = $cmap_offset + $offset; + } + } + + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)', $file)); + } + + // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above + if ($format == 12) { + $this->maxUniChar = 0; + $this->seek($unicode_cmap_offset + 4); + $length = $this->read_ulong(); + $limit = $unicode_cmap_offset + $length; + $this->skip(4); + + $nGroups = $this->read_ulong(); + + $glyphToChar = []; + $charToGlyph = []; + for ($i = 0; $i < $nGroups; $i++) { + $startCharCode = $this->read_ulong(); + $endCharCode = $this->read_ulong(); + $startGlyphCode = $this->read_ulong(); + $offset = 0; + for ($unichar = $startCharCode; $unichar <= $endCharCode; $unichar++) { + $glyph = $startGlyphCode + $offset; + $offset++; + // ZZZ98 + if ($unichar < 0x30000) { + $charToGlyph[$unichar] = $glyph; + $this->maxUniChar = max($unichar, $this->maxUniChar); + $glyphToChar[$glyph][] = $unichar; + } + } + } + } else { + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + } + + // Map Unmapped glyphs - from $numGlyphs + if ($useOTL) { + $bctr = 0xE000; + for ($gid = 1; $gid < $numGlyphs; $gid++) { + if (!isset($glyphToChar[$gid])) { + while (isset($charToGlyph[$bctr])) { + $bctr++; + } // Avoid overwriting a glyph already mapped in PUA + // ZZZ98 + if ($bctr > 0xF8FF && $bctr < 0x2CEB0) { + $bctr = 0x2CEB0; + while (isset($charToGlyph[$bctr])) { + $bctr++; + } + } + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $this->maxUniChar = max($bctr, $this->maxUniChar); + $bctr++; + } + } + } + + // hmtx - Horizontal metrics table + $scale = 1; // not used here + $this->getHMTX($numberOfHMetrics, $numGlyphs, $glyphToChar, $scale); + + // loca - Index to location + $this->getLOCA($indexToLocFormat, $numGlyphs); + + $glyphMap = [0 => 0]; + $glyphSet = [0 => 0]; + $codeToGlyph = []; + + // Set a substitute if ASCII characters do not have glyphs + if (isset($charToGlyph[0x3F])) { + $subs = $charToGlyph[0x3F]; + } else { // Question mark + $subs = $charToGlyph[32]; + } + + foreach ($subset as $code) { + if (isset($charToGlyph[$code])) { + $originalGlyphIdx = $charToGlyph[$code]; + } elseif ($code < 128) { + $originalGlyphIdx = $subs; + } else { + $originalGlyphIdx = 0; + } + if (!isset($glyphSet[$originalGlyphIdx])) { + $glyphSet[$originalGlyphIdx] = count($glyphMap); + $glyphMap[] = $originalGlyphIdx; + } + $codeToGlyph[$code] = $glyphSet[$originalGlyphIdx]; + } + + list($start, $dummy) = $this->get_table_pos('glyf'); + + $n = 0; + while ($n < count($glyphMap)) { + $originalGlyphIdx = $glyphMap[$n]; + $glyphPos = $this->glyphPos[$originalGlyphIdx]; + $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos; + ++$n; + if (!$glyphLen) { + continue; + } + $this->seek($start + $glyphPos); + $numberOfContours = $this->read_short(); + if ($numberOfContours < 0) { + $this->skip(8); + $flags = GlyphOperator::MORE; + while ($flags & GlyphOperator::MORE) { + $flags = $this->read_ushort(); + $glyphIdx = $this->read_ushort(); + if (!isset($glyphSet[$glyphIdx])) { + $glyphSet[$glyphIdx] = count($glyphMap); + $glyphMap[] = $glyphIdx; + } + if ($flags & GlyphOperator::WORDS) { + $this->skip(4); + } else { + $this->skip(2); + } + if ($flags & GlyphOperator::SCALE) { + $this->skip(2); + } elseif ($flags & GlyphOperator::XYSCALE) { + $this->skip(4); + } elseif ($flags & GlyphOperator::TWOBYTWO) { + $this->skip(8); + } + } + } + } + + $numGlyphs = $n = count($glyphMap); + $numberOfHMetrics = $n; + + // MS spec says that "Platform and encoding ID's in the name table should be consistent with those in the cmap table. + // If they are not, the font will not load in Windows" + // Doesn't seem to be a problem? + // Needs to have a name entry in 3,0 (e.g. symbol) - original font will be 3,1 (i.e. Unicode) + $name = $this->get_table('name'); + $name_offset = $this->seek_table("name"); + $format = $this->read_ushort(); + $numRecords = $this->read_ushort(); + $string_data_offset = $name_offset + $this->read_ushort(); + for ($i = 0; $i < $numRecords; $i++) { + $platformId = $this->read_ushort(); + $encodingId = $this->read_ushort(); + if ($platformId == 3 && $encodingId == 1) { + $pos = 6 + ($i * 12) + 2; + $name = $this->_set_ushort($name, $pos, 0x00); // Change encoding to 3,0 rather than 3,1 + } + $this->skip(8); + } + $this->add('name', $name); + + // OS/2 + if (isset($this->tables['OS/2'])) { + $os2 = $this->get_table('OS/2'); + $os2 = $this->_set_ushort($os2, 42, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 44, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 46, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 48, 0x00); // ulCharRange (Unicode ranges) + + $os2 = $this->_set_ushort($os2, 50, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 52, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 54, 0x00); // ulCharRange (Unicode ranges) + $os2 = $this->_set_ushort($os2, 56, 0x00); // ulCharRange (Unicode ranges) + // Set Symbol character only in ulCodePageRange + $os2 = $this->_set_ushort($os2, 78, 0x8000); // ulCodePageRange = Bit #31 Symbol **** 78 = Bit 16-31 + $os2 = $this->_set_ushort($os2, 80, 0x0000); // ulCodePageRange = Bit #31 Symbol **** 80 = Bit 0-15 + $os2 = $this->_set_ushort($os2, 82, 0x0000); // ulCodePageRange = Bit #32- Symbol **** 82 = Bits 48-63 + $os2 = $this->_set_ushort($os2, 84, 0x0000); // ulCodePageRange = Bit #32- Symbol **** 84 = Bits 32-47 + + $os2 = $this->_set_ushort($os2, 64, 0x01); // FirstCharIndex + $os2 = $this->_set_ushort($os2, 66, count($subset)); // LastCharIndex + // Set PANOSE first bit to 5 for Symbol + $os2 = $this->splice($os2, 32, chr(5) . chr(0) . chr(1) . chr(0) . chr(1) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0)); + $this->add('OS/2', $os2); + } + + //tables copied from the original + $tags = ['cvt ', 'fpgm', 'prep', 'gasp']; + foreach ($tags as $tag) { // 1.02 + if (isset($this->tables[$tag])) { + $this->add($tag, $this->get_table($tag)); + } + } + + // post - PostScript + if (isset($this->tables['post'])) { + $opost = $this->get_table('post'); + $post = "\x00\x03\x00\x00" . substr($opost, 4, 12) . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + } + $this->add('post', $post); + + // hhea - Horizontal Header + $hhea = $this->get_table('hhea'); + $hhea = $this->_set_ushort($hhea, 34, $numberOfHMetrics); + $this->add('hhea', $hhea); + + // maxp - Maximum Profile + $maxp = $this->get_table('maxp'); + $maxp = $this->_set_ushort($maxp, 4, $numGlyphs); + $this->add('maxp', $maxp); + + // CMap table Formats [1,0,]6 and [3,0,]4 + // Sort CID2GID map into segments of contiguous codes + $rangeid = 0; + $range = []; + $prevcid = -2; + $prevglidx = -1; + + // for each character + foreach ($subset as $cid => $code) { + $glidx = $codeToGlyph[$code]; + if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) { + $range[$rangeid][] = $glidx; + } else { + // new range + $rangeid = $cid; + $range[$rangeid] = []; + $range[$rangeid][] = $glidx; + } + $prevcid = $cid; + $prevglidx = $glidx; + } + + // cmap - Character to glyph mapping + $segCount = count($range) + 1; // + 1 Last segment has missing character 0xFFFF + $searchRange = 1; + $entrySelector = 0; + + while ($searchRange * 2 <= $segCount) { + $searchRange = $searchRange * 2; + $entrySelector = $entrySelector + 1; + } + + $searchRange = $searchRange * 2; + $rangeShift = $segCount * 2 - $searchRange; + $length = 16 + (8 * $segCount) + ($numGlyphs + 1); + $cmap = [ + 4, $length, 0, // Format 4 Mapping subtable: format, length, language + $segCount * 2, + $searchRange, + $entrySelector, + $rangeShift, + ]; + + // endCode(s) + foreach ($range as $start => $subrange) { + $endCode = $start + (count($subrange) - 1); + $cmap[] = $endCode; // endCode(s) + } + $cmap[] = 0xFFFF; // endCode of last Segment + $cmap[] = 0; // reservedPad + + // startCode(s) + foreach ($range as $start => $subrange) { + $cmap[] = $start; // startCode(s) + } + $cmap[] = 0xFFFF; // startCode of last Segment + + // idDelta(s) + foreach ($range as $start => $subrange) { + $idDelta = -($start - $subrange[0]); + $n += count($subrange); + $cmap[] = $idDelta; // idDelta(s) + } + $cmap[] = 1; // idDelta of last Segment + + // idRangeOffset(s) + foreach ($range as $subrange) { + $cmap[] = 0; // idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0 + } + + $cmap[] = 0; // idRangeOffset of last Segment + foreach ($range as $subrange) { + foreach ($subrange as $glidx) { + $cmap[] = $glidx; + } + } + + $cmap[] = 0; // Mapping for last character + $cmapstr4 = ''; + foreach ($cmap as $cm) { + $cmapstr4 .= pack("n", $cm); + } + + // cmap - Character to glyph mapping + $entryCount = count($subset); + $length = 10 + $entryCount * 2; + + $off = 20 + $length; + $hoff = $off >> 16; + $loff = $off & 0xFFFF; + + $cmap = [ + 0, 2, // Index : version, number of subtables + 1, 0, // Subtable : platform, encoding + 0, 20, // offset (hi,lo) + 3, 0, // Subtable : platform, encoding // See note above for 'name' + $hoff, $loff, // offset (hi,lo) + 6, $length, // Format 6 Mapping table: format, length + 0, 1, // language, First char code + $entryCount, + ]; + + $cmapstr = ''; + foreach ($subset as $code) { + $cmap[] = $codeToGlyph[$code]; + } + + foreach ($cmap as $cm) { + $cmapstr .= pack("n", $cm); + } + + $cmapstr .= $cmapstr4; + $this->add('cmap', $cmapstr); + + // hmtx - Horizontal Metrics + $hmtxstr = ''; + for ($n = 0; $n < $numGlyphs; $n++) { + $originalGlyphIdx = $glyphMap[$n]; + $hm = $this->getHMetric($orignHmetrics, $originalGlyphIdx); + $hmtxstr .= $hm; + } + $this->add('hmtx', $hmtxstr); + + // glyf - Glyph data + list($glyfOffset, $glyfLength) = $this->get_table_pos('glyf'); + if ($glyfLength < $this->maxStrLenRead) { + $glyphData = $this->get_table('glyf'); + } + + $offsets = []; + $glyf = ''; + $pos = 0; + for ($n = 0; $n < $numGlyphs; $n++) { + + $offsets[] = $pos; + $originalGlyphIdx = $glyphMap[$n]; + $glyphPos = $this->glyphPos[$originalGlyphIdx]; + $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos; + + if ($glyfLength < $this->maxStrLenRead) { + $data = substr($glyphData, $glyphPos, $glyphLen); + } else { + if ($glyphLen > 0) { + $data = $this->get_chunk($glyfOffset + $glyphPos, $glyphLen); + } else { + $data = ''; + } + } + + if ($glyphLen > 0) { + $up = unpack('n', substr($data, 0, 2)); + } + + if ($glyphLen > 2 && ($up[1] & (1 << 15))) { + + $pos_in_glyph = 10; + $flags = GlyphOperator::MORE; + + while ($flags & GlyphOperator::MORE) { + $up = unpack('n', substr($data, $pos_in_glyph, 2)); + $flags = $up[1]; + $up = unpack('n', substr($data, $pos_in_glyph + 2, 2)); + $glyphIdx = $up[1]; + $data = $this->_set_ushort($data, $pos_in_glyph + 2, $glyphSet[$glyphIdx]); + $pos_in_glyph += 4; + + if ($flags & GlyphOperator::WORDS) { + $pos_in_glyph += 4; + } else { + $pos_in_glyph += 2; + } + + if ($flags & GlyphOperator::SCALE) { + $pos_in_glyph += 2; + } elseif ($flags & GlyphOperator::XYSCALE) { + $pos_in_glyph += 4; + } elseif ($flags & GlyphOperator::TWOBYTWO) { + $pos_in_glyph += 8; + } + } + } + + $glyf .= $data; + $pos += $glyphLen; + + if ($pos % 4 != 0) { + $padding = 4 - ($pos % 4); + $glyf .= str_repeat("\0", $padding); + $pos += $padding; + } + } + + $offsets[] = $pos; + $this->add('glyf', $glyf); + + // loca - Index to location + $locastr = ''; + if ((($pos + 1) >> 1) > 0xFFFF) { + $indexToLocFormat = 1; // long format + foreach ($offsets as $offset) { + $locastr .= pack("N", $offset); + } + } else { + $indexToLocFormat = 0; // short format + foreach ($offsets as $offset) { + $locastr .= pack("n", ($offset / 2)); + } + } + + $this->add('loca', $locastr); + + // head - Font header + $head = $this->get_table('head'); + $head = $this->_set_ushort($head, 50, $indexToLocFormat); + $this->add('head', $head); + + fclose($this->fh); + + $stm = ''; + $this->endTTFile($stm); + + return $stm; + } + + function getGlyphData($originalGlyphIdx, &$maxdepth, &$depth, &$points, &$contours) + { + $depth++; + $maxdepth = max($maxdepth, $depth); + + if (count($this->glyphdata[$originalGlyphIdx]['compGlyphs'])) { + foreach ($this->glyphdata[$originalGlyphIdx]['compGlyphs'] as $glyphIdx) { + $this->getGlyphData($glyphIdx, $maxdepth, $depth, $points, $contours); + } + } elseif (($this->glyphdata[$originalGlyphIdx]['nContours'] > 0) && $depth > 0) { // simple + $contours += $this->glyphdata[$originalGlyphIdx]['nContours']; + $points += $this->glyphdata[$originalGlyphIdx]['nPoints']; + } + + $depth--; + } + + function getGlyphs($originalGlyphIdx, &$start, &$glyphSet, &$subsetglyphs) + { + $glyphPos = $this->glyphPos[$originalGlyphIdx]; + $glyphLen = $this->glyphPos[$originalGlyphIdx + 1] - $glyphPos; + + if (!$glyphLen) { + return; + } + + $this->seek($start + $glyphPos); + $numberOfContours = $this->read_short(); + + if ($numberOfContours < 0) { + $this->skip(8); + $flags = GlyphOperator::MORE; + while ($flags & GlyphOperator::MORE) { + $flags = $this->read_ushort(); + $glyphIdx = $this->read_ushort(); + if (!isset($glyphSet[$glyphIdx])) { + $glyphSet[$glyphIdx] = count($subsetglyphs); // old glyphID to new glyphID + $subsetglyphs[$glyphIdx] = true; + } + $savepos = ftell($this->fh); + $this->getGlyphs($glyphIdx, $start, $glyphSet, $subsetglyphs); + $this->seek($savepos); + if ($flags & GlyphOperator::WORDS) { + $this->skip(4); + } else { + $this->skip(2); + } + if ($flags & GlyphOperator::SCALE) { + $this->skip(2); + } elseif ($flags & GlyphOperator::XYSCALE) { + $this->skip(4); + } elseif ($flags & GlyphOperator::TWOBYTWO) { + $this->skip(8); + } + } + } + } + + function getHMTX($numberOfHMetrics, $numGlyphs, &$glyphToChar, $scale) + { + $start = $this->seek_table('hmtx'); + $aw = 0; + $this->charWidths = str_pad('', 256 * 256 * 2, "\x00"); + + if ($this->maxUniChar > 65536) { + $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00"); + } // Plane 1 SMP + + if ($this->maxUniChar > 131072) { + $this->charWidths .= str_pad('', 256 * 256 * 2, "\x00"); + } // Plane 2 SMP + + $nCharWidths = 0; + if (($numberOfHMetrics * 4) < $this->maxStrLenRead) { + $data = $this->get_chunk($start, $numberOfHMetrics * 4); + $arr = unpack('n*', $data); + } else { + $this->seek($start); + } + + for ($glyph = 0; $glyph < $numberOfHMetrics; $glyph++) { + + if (($numberOfHMetrics * 4) < $this->maxStrLenRead) { + $aw = $arr[($glyph * 2) + 1]; + } else { + $aw = $this->read_ushort(); + $lsb = $this->read_ushort(); + } + if (isset($glyphToChar[$glyph]) || $glyph == 0) { + if ($aw >= (1 << 15)) { + $aw = 0; + } + + // 1.03 Some (arabic) fonts have -ve values for width + // although should be unsigned value - comes out as e.g. 65108 (intended -50) + if ($glyph === 0) { + $this->defaultWidth = $scale * $aw; + continue; + } + + foreach ($glyphToChar[$glyph] as $char) { + if ($char != 0 && $char != 65535) { + $w = (int) round($scale * $aw); + if ($w === 0) { + $w = 65535; + } + if ($char < 196608) { + $this->charWidths[$char * 2] = chr($w >> 8); + $this->charWidths[$char * 2 + 1] = chr($w & 0xFF); + $nCharWidths++; + } + } + } + } + } + + $data = $this->get_chunk(($start + $numberOfHMetrics * 4), ($numGlyphs * 2)); + $arr = unpack("n*", $data); + $diff = $numGlyphs - $numberOfHMetrics; + $w = (int) round($scale * $aw); + if ($w === 0) { + $w = 65535; + } + for ($pos = 0; $pos < $diff; $pos++) { + $glyph = $pos + $numberOfHMetrics; + if (isset($glyphToChar[$glyph])) { + foreach ($glyphToChar[$glyph] as $char) { + if ($char != 0 && $char != 65535) { + if ($char < 196608) { + $this->charWidths[$char * 2] = chr($w >> 8); + $this->charWidths[$char * 2 + 1] = chr($w & 0xFF); + $nCharWidths++; + } + } + } + } + } + + // NB 65535 is a set width of 0 + // First bytes define number of chars in font + $this->charWidths[0] = chr($nCharWidths >> 8); + $this->charWidths[1] = chr($nCharWidths & 0xFF); + } + + function getHMetric($numberOfHMetrics, $gid) + { + $start = $this->seek_table("hmtx"); + if ($gid < $numberOfHMetrics) { + $this->seek($start + ($gid * 4)); + $hm = fread($this->fh, 4); + } else { + $this->seek($start + (($numberOfHMetrics - 1) * 4)); + $hm = fread($this->fh, 2); + $this->seek($start + ($numberOfHMetrics * 2) + ($gid * 2)); + $hm .= fread($this->fh, 2); + } + + return $hm; + } + + function getLOCA($indexToLocFormat, $numGlyphs) + { + $start = $this->seek_table('loca'); + $this->glyphPos = []; + if ($indexToLocFormat == 0) { + $data = $this->get_chunk($start, ($numGlyphs * 2) + 2); + $arr = unpack("n*", $data); + for ($n = 0; $n <= $numGlyphs; $n++) { + $this->glyphPos[] = ($arr[$n + 1] * 2); + } + } elseif ($indexToLocFormat == 1) { + $data = $this->get_chunk($start, ($numGlyphs * 4) + 4); + $arr = unpack("N*", $data); + for ($n = 0; $n <= $numGlyphs; $n++) { + $this->glyphPos[] = ($arr[$n + 1]); + } + } else { + throw new \Mpdf\Exception\FontException('Unknown location table format ' . $indexToLocFormat); + } + } + + /** + * CMAP Format 4 + */ + function getCMAP4($unicode_cmap_offset, &$glyphToChar, &$charToGlyph) + { + $this->maxUniChar = 0; + $this->seek($unicode_cmap_offset + 2); + $length = $this->read_ushort(); + $limit = $unicode_cmap_offset + $length; + $this->skip(2); + + $segCount = $this->read_ushort() / 2; + $this->skip(6); + $endCount = []; + + for ($i = 0; $i < $segCount; $i++) { + $endCount[] = $this->read_ushort(); + } + + $this->skip(2); + $startCount = []; + + for ($i = 0; $i < $segCount; $i++) { + $startCount[] = $this->read_ushort(); + } + + $idDelta = []; + + for ($i = 0; $i < $segCount; $i++) { + $idDelta[] = $this->read_short(); + } // ???? was unsigned short + + $idRangeOffset_start = $this->_pos; + $idRangeOffset = []; + + for ($i = 0; $i < $segCount; $i++) { + $idRangeOffset[] = $this->read_ushort(); + } + + for ($n = 0; $n < $segCount; $n++) { + $endpoint = ($endCount[$n] + 1); + for ($unichar = $startCount[$n]; $unichar < $endpoint; $unichar++) { + if ($idRangeOffset[$n] == 0) { + $glyph = ($unichar + $idDelta[$n]) & 0xFFFF; + } else { + $offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n]; + $offset = $idRangeOffset_start + 2 * $n + $offset; + if ($offset >= $limit) { + $glyph = 0; + } else { + $glyph = $this->get_ushort($offset); + if ($glyph != 0) { + $glyph = ($glyph + $idDelta[$n]) & 0xFFFF; + } + } + } + $charToGlyph[$unichar] = $glyph; + if ($unichar < 196608) { + $this->maxUniChar = max($unichar, $this->maxUniChar); + } + $glyphToChar[$glyph][] = $unichar; + } + } + } + + function endTTFile(&$stm) + { + $stm = ''; + $numTables = count($this->otables); + $searchRange = 1; + $entrySelector = 0; + while ($searchRange * 2 <= $numTables) { + $searchRange *= 2; + $entrySelector += 1; + } + $searchRange *= 16; + $rangeShift = $numTables * 16 - $searchRange; + + // Header + if (_TTF_MAC_HEADER) { + $stm .= pack('Nnnnn', 0x74727565, $numTables, $searchRange, $entrySelector, $rangeShift); // Mac + } else { + $stm .= pack('Nnnnn', 0x00010000, $numTables, $searchRange, $entrySelector, $rangeShift); // Windows + } + + // Table directory + $tables = $this->otables; + ksort($tables); + $offset = 12 + $numTables * 16; + foreach ($tables as $tag => $data) { + if ($tag === 'head') { + $head_start = $offset; + } + $stm .= $tag; + $checksum = $this->calcChecksum($data); + $stm .= pack('nn', $checksum[0], $checksum[1]); + $stm .= pack('NN', $offset, strlen($data)); + $paddedLength = (strlen($data) + 3) & ~3; + $offset += $paddedLength; + } + + // Table data + foreach ($tables as $tag => $data) { + $data .= "\0\0\0"; + $stm .= substr($data, 0, (strlen($data) & ~3)); + } + + $checksum = $this->calcChecksum($stm); + $checksum = $this->sub32([0xB1B0, 0xAFBA], $checksum); + $chk = pack("nn", $checksum[0], $checksum[1]); + $stm = $this->splice($stm, ($head_start + 8), $chk); + + return $stm; + } + + function repackageTTF($file, $TTCfontID = 0, $debug = false, $useOTL = false) + { + $this->useOTL = $useOTL; + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + + if (!$this->fh) { + throw new \Mpdf\Exception\FontException(sprintf('Unable to open file "%s"', $file)); + } + + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->ascent = 0; + $this->descent = 0; + $this->strikeoutSize = 0; + $this->strikeoutPosition = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->skip(4); + $this->maxUni = 0; + + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000], true)) { + throw new \Mpdf\Exception\FontException(sprintf('Error parsing TrueType Collection: version=%s - %s', $version, $file)); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + } + + $this->readTableDirectory($debug); + $tags = ['OS/2', 'glyf', 'head', 'hhea', 'hmtx', 'loca', 'maxp', 'name', 'post', 'cvt ', 'fpgm', 'gasp', 'prep']; + + foreach ($tags as $tag) { + if (isset($this->tables[$tag])) { + $this->add($tag, $this->get_table($tag)); + } + } + + if ($useOTL) { + + // maxp - Maximum profile table + $this->seek_table('maxp'); + $this->skip(4); + $numGlyphs = $this->read_ushort(); + + // cmap - Character to glyph index mapping table + $cmap_offset = $this->seek_table('cmap'); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\Exception\FontException(sprintf('Font "%s" does not have cmap for Unicode (platform 3, encoding 1, format 4, or platform 0, any encoding, format 4)', $this->filename)); + } + + $glyphToChar = []; + $charToGlyph = []; + $this->getCMAP4($unicode_cmap_offset, $glyphToChar, $charToGlyph); + + // Map Unmapped glyphs - from $numGlyphs + $bctr = 0xE000; + for ($gid = 1; $gid < $numGlyphs; $gid++) { + if (!isset($glyphToChar[$gid])) { + while (isset($charToGlyph[$bctr])) { + $bctr++; + } // Avoid overwriting a glyph already mapped in PUA (6,400) + if ($bctr > 0xF8FF) { + throw new \Mpdf\Exception\FontException("Problem. Trying to repackage TF file; not enough space for unmapped glyphs"); + } + $glyphToChar[$gid][] = $bctr; + $charToGlyph[$bctr] = $gid; + $bctr++; + } + } + + // Sort CID2GID map into segments of contiguous codes + unset($charToGlyph[65535]); + unset($charToGlyph[0]); + + ksort($charToGlyph); + $rangeid = 0; + $range = []; + $prevcid = -2; + $prevglidx = -1; + + // for each character + foreach ($charToGlyph as $cid => $glidx) { + if ($cid == ($prevcid + 1) && $glidx == ($prevglidx + 1)) { + $range[$rangeid][] = $glidx; + } else { + // new range + $rangeid = $cid; + $range[$rangeid] = []; + $range[$rangeid][] = $glidx; + } + $prevcid = $cid; + $prevglidx = $glidx; + } + + // CMap table + // cmap - Character to glyph mapping + $segCount = count($range) + 1; // + 1 Last segment has missing character 0xFFFF + $searchRange = 1; + $entrySelector = 0; + + while ($searchRange * 2 <= $segCount) { + $searchRange *= 2; + ++$entrySelector; + } + + $searchRange *= 2; + $rangeShift = $segCount * 2 - $searchRange; + $length = 16 + (8 * $segCount) + ($numGlyphs + 1); + $cmap = [0, 3, // Index : version, number of encoding subtables + 0, 0, // Encoding Subtable : platform (UNI=0), encoding 0 + 0, 28, // Encoding Subtable : offset (hi,lo) + 0, 3, // Encoding Subtable : platform (UNI=0), encoding 3 + 0, 28, // Encoding Subtable : offset (hi,lo) + 3, 1, // Encoding Subtable : platform (MS=3), encoding 1 + 0, 28, // Encoding Subtable : offset (hi,lo) + 4, $length, 0, // Format 4 Mapping subtable: format, length, language + $segCount * 2, + $searchRange, + $entrySelector, + $rangeShift]; + + // endCode(s) + foreach ($range as $start => $subrange) { + $endCode = $start + (count($subrange) - 1); + $cmap[] = $endCode; // endCode(s) + } + $cmap[] = 0xFFFF; // endCode of last Segment + $cmap[] = 0; // reservedPad + + // startCode(s) + foreach ($range as $start => $subrange) { + $cmap[] = $start; // startCode(s) + } + $cmap[] = 0xFFFF; // startCode of last Segment + + // idDelta(s) + foreach ($range as $start => $subrange) { + $idDelta = -($start - $subrange[0]); + $cmap[] = $idDelta; // idDelta(s) + } + + $cmap[] = 1; // idDelta of last Segment + // idRangeOffset(s) + foreach ($range as $subrange) { + $cmap[] = 0; // idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0 + } + + $cmap[] = 0; // idRangeOffset of last Segment + foreach ($range as $subrange) { + foreach ($subrange as $glidx) { + $cmap[] = $glidx; + } + } + $cmap[] = 0; // Mapping for last character + $cmapstr = ''; + foreach ($cmap as $cm) { + $cmapstr .= pack('n', $cm); + } + + $this->add('cmap', $cmapstr); + } else { + $this->add('cmap', $this->get_table('cmap')); + } + + fclose($this->fh); + $stm = ''; + $this->endTTFile($stm); + + return $stm; + } +} diff --git a/src/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php b/src/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php new file mode 100644 index 000000000..b58fc5916 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php @@ -0,0 +1,454 @@ +<?php + +namespace Mpdf; + +class TTFontFileAnalysis extends TTFontFile +{ + + // Used to get font information from files in directory + function extractCoreInfo($file, $TTCfontID = 0) + { + $this->filename = $file; + $this->fh = fopen($file, 'rb'); + if (!$this->fh) { + throw new \Mpdf\MpdfException('ERROR - Can\'t open file ' . $file); + } + $this->_pos = 0; + $this->charWidths = ''; + $this->glyphPos = []; + $this->charToGlyph = []; + $this->tables = []; + $this->otables = []; + $this->ascent = 0; + $this->descent = 0; + $this->numTTCFonts = 0; + $this->TTCFonts = []; + $this->version = $version = $this->read_ulong(); + $this->panose = []; // mPDF 5.0 + + if ($version == 0x4F54544F) { + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); + } + + if ($version == 0x74746366) { + if ($TTCfontID > 0) { + $this->version = $version = $this->read_ulong(); // TTC Header version now + if (!in_array($version, [0x00010000, 0x00020000])) { + throw new \Mpdf\MpdfException("ERROR - NOT ADDED as Error parsing TrueType Collection: version=" . $version . " - " . $file); + } + } else { + throw new \Mpdf\MpdfException("ERROR - Error parsing TrueType Collection - " . $file); + } + $this->numTTCFonts = $this->read_ulong(); + for ($i = 1; $i <= $this->numTTCFonts; $i++) { + $this->TTCFonts[$i]['offset'] = $this->read_ulong(); + } + $this->seek($this->TTCFonts[$TTCfontID]['offset']); + $this->version = $version = $this->read_ulong(); // TTFont version again now + $this->readTableDirectory(false); + } else { + if (!in_array($version, [0x00010000, 0x74727565])) { + throw new \Mpdf\MpdfException("ERROR - NOT ADDED as Not a TrueType font: version=" . $version . " - " . $file); + } + $this->readTableDirectory(false); + } + + /* Included for testing... + $cmap_offset = $this->seek_table("cmap"); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i=0;$i<$cmapTableCount;$i++) { + $x[$i]['platformId'] = $this->read_ushort(); + $x[$i]['encodingId'] = $this->read_ushort(); + $x[$i]['offset'] = $this->read_ulong(); + $save_pos = $this->_pos; + $x[$i]['format'] = $this->get_ushort($cmap_offset + $x[$i]['offset'] ); + $this->seek($save_pos ); + } + print_r($x); exit; + */ + /////////////////////////////////// + // name - Naming table + /////////////////////////////////// + + /* Test purposes - displays table of names + $name_offset = $this->seek_table("name"); + $format = $this->read_ushort(); + if ($format != 0 && $format != 1) // mPDF 5.3.73 + die("Unknown name table format ".$format); + $numRecords = $this->read_ushort(); + $string_data_offset = $name_offset + $this->read_ushort(); + for ($i=0;$i<$numRecords; $i++) { + $x[$i]['platformId'] = $this->read_ushort(); + $x[$i]['encodingId'] = $this->read_ushort(); + $x[$i]['languageId'] = $this->read_ushort(); + $x[$i]['nameId'] = $this->read_ushort(); + $x[$i]['length'] = $this->read_ushort(); + $x[$i]['offset'] = $this->read_ushort(); + + $N = ''; + if ($x[$i]['platformId'] == 1 && $x[$i]['encodingId'] == 0 && $x[$i]['languageId'] == 0) { // Roman + $opos = $this->_pos; + $N = $this->get_chunk($string_data_offset + $x[$i]['offset'] , $x[$i]['length'] ); + $this->_pos = $opos; + $this->seek($opos); + } + else { // Unicode + $opos = $this->_pos; + $this->seek($string_data_offset + $x[$i]['offset'] ); + $length = $x[$i]['length'] ; + if ($length % 2 != 0) + $length -= 1; + // die("PostScript name is UTF-16BE string of odd length"); + $length /= 2; + $N = ''; + while ($length > 0) { + $char = $this->read_ushort(); + $N .= (chr($char)); + $length -= 1; + } + $this->_pos = $opos; + $this->seek($opos); + } + $x[$i]['names'][$nameId] = $N; + } + print_r($x); exit; + */ + + $name_offset = $this->seek_table("name"); + $format = $this->read_ushort(); + if ($format != 0 && $format != 1) { // mPDF 5.3.73 + throw new \Mpdf\MpdfException("ERROR - NOT ADDED as Unknown name table format " . $format . " - " . $file); + } + $numRecords = $this->read_ushort(); + $string_data_offset = $name_offset + $this->read_ushort(); + $names = [1 => '', 2 => '', 3 => '', 4 => '', 6 => '']; + $K = array_keys($names); + $nameCount = count($names); + for ($i = 0; $i < $numRecords; $i++) { + $platformId = $this->read_ushort(); + $encodingId = $this->read_ushort(); + $languageId = $this->read_ushort(); + $nameId = $this->read_ushort(); + $length = $this->read_ushort(); + $offset = $this->read_ushort(); + if (!in_array($nameId, $K)) { + continue; + } + $N = ''; + if ($platformId == 3 && $encodingId == 1 && $languageId == 0x409) { // Microsoft, Unicode, US English, PS Name + $opos = $this->_pos; + $this->seek($string_data_offset + $offset); + if ($length % 2 != 0) { + $length += 1; + } + $length /= 2; + $N = ''; + while ($length > 0) { + $char = $this->read_ushort(); + $N .= (chr($char)); + $length -= 1; + } + $this->_pos = $opos; + $this->seek($opos); + } elseif ($platformId == 1 && $encodingId == 0 && $languageId == 0) { // Macintosh, Roman, English, PS Name + $opos = $this->_pos; + $N = $this->get_chunk($string_data_offset + $offset, $length); + $this->_pos = $opos; + $this->seek($opos); + } + if ($N && $names[$nameId] == '') { + $names[$nameId] = $N; + $nameCount -= 1; + if ($nameCount == 0) { + break; + } + } + } + if ($names[6]) { + $psName = preg_replace('/ /', '-', $names[6]); + } elseif ($names[4]) { + $psName = preg_replace('/ /', '-', $names[4]); + } elseif ($names[1]) { + $psName = preg_replace('/ /', '-', $names[1]); + } else { + $psName = ''; + } + if (!$names[1] && !$psName) { + throw new \Mpdf\MpdfException("ERROR - NOT ADDED as Could not find valid font name - " . $file); + } + $this->name = $psName; + if ($names[1]) { + $this->familyName = $names[1]; + } else { + $this->familyName = $psName; + } + if ($names[2]) { + $this->styleName = $names[2]; + } else { + $this->styleName = 'Regular'; + } + + /////////////////////////////////// + // head - Font header table + /////////////////////////////////// + $this->seek_table("head"); + $ver_maj = $this->read_ushort(); + $ver_min = $this->read_ushort(); + if ($ver_maj != 1) { + throw new \Mpdf\MpdfException('ERROR - NOT ADDED as Unknown head table version ' . $ver_maj . '.' . $ver_min . " - " . $file); + } + $this->fontRevision = $this->read_ushort() . $this->read_ushort(); + $this->skip(4); + $magic = $this->read_ulong(); + if ($magic != 0x5F0F3CF5) { + throw new \Mpdf\MpdfException('ERROR - NOT ADDED as Invalid head table magic ' . $magic . " - " . $file); + } + $this->skip(2); + $this->unitsPerEm = $unitsPerEm = $this->read_ushort(); + $scale = 1000 / $unitsPerEm; + $this->skip(24); + $macStyle = $this->read_short(); + $this->skip(4); + $indexLocFormat = $this->read_short(); + + /////////////////////////////////// + // OS/2 - OS/2 and Windows metrics table + /////////////////////////////////// + $sFamily = ''; + $panose = ''; + $fsSelection = ''; + if (isset($this->tables["OS/2"])) { + $this->seek_table("OS/2"); + $this->skip(30); + $sF = $this->read_short(); + $sFamily = ($sF >> 8); + $this->_pos += 10; //PANOSE = 10 byte length + $panose = fread($this->fh, 10); + $this->panose = []; + for ($p = 0; $p < strlen($panose); $p++) { + $this->panose[] = ord($panose[$p]); + } + $this->skip(20); + $fsSelection = $this->read_short(); + } + + /////////////////////////////////// + // post - PostScript table + /////////////////////////////////// + $this->seek_table("post"); + $this->skip(4); + $this->italicAngle = $this->read_short() + $this->read_ushort() / 65536.0; + $this->skip(4); + $isFixedPitch = $this->read_ulong(); + + + + /////////////////////////////////// + // cmap - Character to glyph index mapping table + /////////////////////////////////// + $cmap_offset = $this->seek_table("cmap"); + $this->skip(2); + $cmapTableCount = $this->read_ushort(); + $unicode_cmap_offset = 0; + for ($i = 0; $i < $cmapTableCount; $i++) { + $platformID = $this->read_ushort(); + $encodingID = $this->read_ushort(); + $offset = $this->read_ulong(); + $save_pos = $this->_pos; + if (($platformID == 3 && $encodingID == 1) || $platformID == 0) { // Microsoft, Unicode + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 4) { + if (!$unicode_cmap_offset) { + $unicode_cmap_offset = $cmap_offset + $offset; + } + } + } elseif ((($platformID == 3 && $encodingID == 10) || $platformID == 0)) { // Microsoft, Unicode Format 12 table HKCS + $format = $this->get_ushort($cmap_offset + $offset); + if ($format == 12) { + $unicode_cmap_offset = $cmap_offset + $offset; + break; + } + } + $this->seek($save_pos); + } + + if (!$unicode_cmap_offset) { + throw new \Mpdf\MpdfException('ERROR - Font (' . $this->filename . ') NOT ADDED as it is not Unicode encoded, and cannot be used by mPDF'); + } + + $rtl = false; + $indic = false; + $cjk = false; + $sip = false; + $smp = false; + $pua = false; + $puaag = false; + $glyphToChar = []; + $unAGlyphs = ''; + // Format 12 CMAP does characters above Unicode BMP i.e. some HKCS characters U+20000 and above + if ($format == 12) { + $this->seek($unicode_cmap_offset + 4); + $length = $this->read_ulong(); + $limit = $unicode_cmap_offset + $length; + $this->skip(4); + $nGroups = $this->read_ulong(); + for ($i = 0; $i < $nGroups; $i++) { + $startCharCode = $this->read_ulong(); + $endCharCode = $this->read_ulong(); + $startGlyphCode = $this->read_ulong(); + if (($endCharCode > 0x20000 && $endCharCode < 0x2A6DF) || ($endCharCode > 0x2F800 && $endCharCode < 0x2FA1F)) { + $sip = true; + } + if ($endCharCode > 0x10000 && $endCharCode < 0x1FFFF) { + $smp = true; + } + if (($endCharCode > 0x0590 && $endCharCode < 0x077F) || ($endCharCode > 0xFE70 && $endCharCode < 0xFEFF) || ($endCharCode > 0xFB50 && $endCharCode < 0xFDFF)) { + $rtl = true; + } + if ($endCharCode > 0x0900 && $endCharCode < 0x0DFF) { + $indic = true; + } + if ($endCharCode > 0xE000 && $endCharCode < 0xF8FF) { + $pua = true; + if ($endCharCode > 0xF500 && $endCharCode < 0xF7FF) { + $puaag = true; + } + } + if (($endCharCode > 0x2E80 && $endCharCode < 0x4DC0) || ($endCharCode > 0x4E00 && $endCharCode < 0xA4CF) || ($endCharCode > 0xAC00 && $endCharCode < 0xD7AF) || ($endCharCode > 0xF900 && $endCharCode < 0xFAFF) || ($endCharCode > 0xFE30 && $endCharCode < 0xFE4F)) { + $cjk = true; + } + + $offset = 0; + // Get each glyphToChar - only point if going to analyse un-mapped Arabic Glyphs + if (isset($this->tables['post'])) { + for ($unichar = $startCharCode; $unichar <= $endCharCode; $unichar++) { + $glyph = $startGlyphCode + $offset; + $offset++; + $glyphToChar[$glyph][] = $unichar; + } + } + } + } else { // Format 4 CMap + $this->seek($unicode_cmap_offset + 2); + $length = $this->read_ushort(); + $limit = $unicode_cmap_offset + $length; + $this->skip(2); + + $segCount = $this->read_ushort() / 2; + $this->skip(6); + $endCount = []; + for ($i = 0; $i < $segCount; $i++) { + $endCount[] = $this->read_ushort(); + } + $this->skip(2); + $startCount = []; + for ($i = 0; $i < $segCount; $i++) { + $startCount[] = $this->read_ushort(); + } + $idDelta = []; + for ($i = 0; $i < $segCount; $i++) { + $idDelta[] = $this->read_short(); + } + $idRangeOffset_start = $this->_pos; + $idRangeOffset = []; + for ($i = 0; $i < $segCount; $i++) { + $idRangeOffset[] = $this->read_ushort(); + } + + for ($n = 0; $n < $segCount; $n++) { + if (($endCount[$n] > 0x0590 && $endCount[$n] < 0x077F) || ($endCount[$n] > 0xFE70 && $endCount[$n] < 0xFEFF) || ($endCount[$n] > 0xFB50 && $endCount[$n] < 0xFDFF)) { + $rtl = true; + } + if ($endCount[$n] > 0x0900 && $endCount[$n] < 0x0DFF) { + $indic = true; + } + if (($endCount[$n] > 0x2E80 && $endCount[$n] < 0x4DC0) || ($endCount[$n] > 0x4E00 && $endCount[$n] < 0xA4CF) || ($endCount[$n] > 0xAC00 && $endCount[$n] < 0xD7AF) || ($endCount[$n] > 0xF900 && $endCount[$n] < 0xFAFF) || ($endCount[$n] > 0xFE30 && $endCount[$n] < 0xFE4F)) { + $cjk = true; + } + if ($endCount[$n] > 0xE000 && $endCount[$n] < 0xF8FF) { + $pua = true; + if ($endCount[$n] > 0xF500 && $endCount[$n] < 0xF7FF) { + $puaag = true; + } + } + // Get each glyphToChar - only point if going to analyse un-mapped Arabic Glyphs + if (isset($this->tables['post'])) { + $endpoint = ($endCount[$n] + 1); + for ($unichar = $startCount[$n]; $unichar < $endpoint; $unichar++) { + if ($idRangeOffset[$n] == 0) { + $glyph = ($unichar + $idDelta[$n]) & 0xFFFF; + } else { + $offset = ($unichar - $startCount[$n]) * 2 + $idRangeOffset[$n]; + $offset = $idRangeOffset_start + 2 * $n + $offset; + if ($offset >= $limit) { + $glyph = 0; + } else { + $glyph = $this->get_ushort($offset); + if ($glyph != 0) { + $glyph = ($glyph + $idDelta[$n]) & 0xFFFF; + } + } + } + $glyphToChar[$glyph][] = $unichar; + } + } + } + } + + + $bold = false; + $italic = false; + $ftype = ''; + if ($macStyle & (1 << 0)) { + $bold = true; + } // bit 0 bold + elseif ($fsSelection & (1 << 5)) { + $bold = true; + } // 5 BOLD Characters are emboldened + + if ($macStyle & (1 << 1)) { + $italic = true; + } // bit 1 italic + elseif ($fsSelection & (1 << 0)) { + $italic = true; + } // 0 ITALIC Font contains Italic characters, otherwise they are upright + elseif ($this->italicAngle <> 0) { + $italic = true; + } + + if ($isFixedPitch) { + $ftype = 'mono'; + } elseif ($sFamily > 0 && $sFamily < 8) { + $ftype = 'serif'; + } elseif ($sFamily == 8) { + $ftype = 'sans'; + } elseif ($sFamily == 10) { + $ftype = 'cursive'; + } + // Use PANOSE + if ($panose) { + $bFamilyType = ord($panose[0]); + if ($bFamilyType == 2) { + $bSerifStyle = ord($panose[1]); + if (!$ftype) { + if ($bSerifStyle > 1 && $bSerifStyle < 11) { + $ftype = 'serif'; + } elseif ($bSerifStyle > 10) { + $ftype = 'sans'; + } + } + $bProportion = ord($panose[3]); + if ($bProportion == 9 || $bProportion == 1) { + $ftype = 'mono'; + } // ==1 i.e. No Fit needed for OCR-a and -b + } elseif ($bFamilyType == 3) { + $ftype = 'cursive'; + } + } + + fclose($this->fh); + return [$this->familyName, $bold, $italic, $ftype, $TTCfontID, $rtl, $indic, $cjk, $sip, $smp, $puaag, $pua, $unAGlyphs]; + } +} diff --git a/src/vendor/mpdf/mpdf/src/TableOfContents.php b/src/vendor/mpdf/mpdf/src/TableOfContents.php new file mode 100644 index 000000000..82ce748e8 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/TableOfContents.php @@ -0,0 +1,908 @@ +<?php + +namespace Mpdf; + +use Mpdf\Utils\Arrays; +use DeepCopy\DeepCopy; + +class TableOfContents +{ + + private $mpdf; + + private $sizeConverter; + + var $_toc; + + var $TOCmark; + + var $TOCoutdent; // mPDF 5.6.31 + + var $TOCpreHTML; + + var $TOCpostHTML; + + var $TOCbookmarkText; + + var $TOCusePaging; + + var $TOCuseLinking; + + var $TOCorientation; + + var $TOC_margin_left; + + var $TOC_margin_right; + + var $TOC_margin_top; + + var $TOC_margin_bottom; + + var $TOC_margin_header; + + var $TOC_margin_footer; + + var $TOC_odd_header_name; + + var $TOC_even_header_name; + + var $TOC_odd_footer_name; + + var $TOC_even_footer_name; + + var $TOC_odd_header_value; + + var $TOC_even_header_value; + + var $TOC_odd_footer_value; + + var $TOC_even_footer_value; + + var $TOC_page_selector; + + var $TOC_resetpagenum; // mPDF 6 + + var $TOC_pagenumstyle; // mPDF 6 + + var $TOC_suppress; // mPDF 6 + + var $TOCsheetsize; + + var $m_TOC; + + /** + * @var bool Determine if the TOC should be cloned to calculate the correct page numbers + */ + protected $tocTocPaintBegun = false; + + public function __construct(Mpdf $mpdf, SizeConverter $sizeConverter) + { + $this->mpdf = $mpdf; + $this->sizeConverter = $sizeConverter; + + $this->_toc = []; + $this->TOCmark = 0; + $this->m_TOC = []; + } + + /** + * Mark the TOC Paint as having begun + */ + public function beginTocPaint() + { + $this->tocTocPaintBegun = true; + } + + public function TOCpagebreak( + $tocfont = '', + $tocfontsize = '', + $tocindent = '', + $TOCusePaging = true, + $TOCuseLinking = '', + $toc_orientation = '', + $toc_mgl = '', + $toc_mgr = '', + $toc_mgt = '', + $toc_mgb = '', + $toc_mgh = '', + $toc_mgf = '', + $toc_ohname = '', + $toc_ehname = '', + $toc_ofname = '', + $toc_efname = '', + $toc_ohvalue = 0, + $toc_ehvalue = 0, + $toc_ofvalue = 0, + $toc_efvalue = 0, + $toc_preHTML = '', + $toc_postHTML = '', + $toc_bookmarkText = '', + $resetpagenum = '', + $pagenumstyle = '', + $suppress = '', + $orientation = '', + $mgl = '', + $mgr = '', + $mgt = '', + $mgb = '', + $mgh = '', + $mgf = '', + $ohname = '', + $ehname = '', + $ofname = '', + $efname = '', + $ohvalue = 0, + $ehvalue = 0, + $ofvalue = 0, + $efvalue = 0, + $toc_id = 0, + $pagesel = '', + $toc_pagesel = '', + $sheetsize = '', + $toc_sheetsize = '', + $tocoutdent = '', + $toc_resetpagenum = '', + $toc_pagenumstyle = '', + $toc_suppress = '' + ) { + + if (strtoupper($toc_id) == 'ALL') { + $toc_id = '_mpdf_all'; + } elseif (!$toc_id) { + $toc_id = 0; + } else { + $toc_id = strtolower($toc_id); + } + + if ($TOCusePaging === false || strtolower($TOCusePaging) == "off" || $TOCusePaging === 0 || $TOCusePaging === "0" || $TOCusePaging === "") { + $TOCusePaging = false; + } else { + $TOCusePaging = true; + } + if (!$TOCuseLinking) { + $TOCuseLinking = false; + } + if ($toc_id) { + $this->m_TOC[$toc_id]['TOCmark'] = $this->mpdf->page; + $this->m_TOC[$toc_id]['TOCoutdent'] = $tocoutdent; + $this->m_TOC[$toc_id]['TOCorientation'] = $toc_orientation; + $this->m_TOC[$toc_id]['TOCuseLinking'] = $TOCuseLinking; + $this->m_TOC[$toc_id]['TOCusePaging'] = $TOCusePaging; + + if ($toc_preHTML) { + $this->m_TOC[$toc_id]['TOCpreHTML'] = $toc_preHTML; + } + if ($toc_postHTML) { + $this->m_TOC[$toc_id]['TOCpostHTML'] = $toc_postHTML; + } + if ($toc_bookmarkText) { + $this->m_TOC[$toc_id]['TOCbookmarkText'] = $toc_bookmarkText; + } + + $this->m_TOC[$toc_id]['TOC_margin_left'] = $toc_mgl; + $this->m_TOC[$toc_id]['TOC_margin_right'] = $toc_mgr; + $this->m_TOC[$toc_id]['TOC_margin_top'] = $toc_mgt; + $this->m_TOC[$toc_id]['TOC_margin_bottom'] = $toc_mgb; + $this->m_TOC[$toc_id]['TOC_margin_header'] = $toc_mgh; + $this->m_TOC[$toc_id]['TOC_margin_footer'] = $toc_mgf; + $this->m_TOC[$toc_id]['TOC_odd_header_name'] = $toc_ohname; + $this->m_TOC[$toc_id]['TOC_even_header_name'] = $toc_ehname; + $this->m_TOC[$toc_id]['TOC_odd_footer_name'] = $toc_ofname; + $this->m_TOC[$toc_id]['TOC_even_footer_name'] = $toc_efname; + $this->m_TOC[$toc_id]['TOC_odd_header_value'] = $toc_ohvalue; + $this->m_TOC[$toc_id]['TOC_even_header_value'] = $toc_ehvalue; + $this->m_TOC[$toc_id]['TOC_odd_footer_value'] = $toc_ofvalue; + $this->m_TOC[$toc_id]['TOC_even_footer_value'] = $toc_efvalue; + $this->m_TOC[$toc_id]['TOC_page_selector'] = $toc_pagesel; + $this->m_TOC[$toc_id]['TOC_resetpagenum'] = $toc_resetpagenum; // mPDF 6 + $this->m_TOC[$toc_id]['TOC_pagenumstyle'] = $toc_pagenumstyle; // mPDF 6 + $this->m_TOC[$toc_id]['TOC_suppress'] = $toc_suppress; // mPDF 6 + $this->m_TOC[$toc_id]['TOCsheetsize'] = $toc_sheetsize; + } else { + $this->TOCmark = $this->mpdf->page; + $this->TOCoutdent = $tocoutdent; + $this->TOCorientation = $toc_orientation; + $this->TOCuseLinking = $TOCuseLinking; + $this->TOCusePaging = $TOCusePaging; + + if ($toc_preHTML) { + $this->TOCpreHTML = $toc_preHTML; + } + if ($toc_postHTML) { + $this->TOCpostHTML = $toc_postHTML; + } + if ($toc_bookmarkText) { + $this->TOCbookmarkText = $toc_bookmarkText; + } + + $this->TOC_margin_left = $toc_mgl; + $this->TOC_margin_right = $toc_mgr; + $this->TOC_margin_top = $toc_mgt; + $this->TOC_margin_bottom = $toc_mgb; + $this->TOC_margin_header = $toc_mgh; + $this->TOC_margin_footer = $toc_mgf; + $this->TOC_odd_header_name = $toc_ohname; + $this->TOC_even_header_name = $toc_ehname; + $this->TOC_odd_footer_name = $toc_ofname; + $this->TOC_even_footer_name = $toc_efname; + $this->TOC_odd_header_value = $toc_ohvalue; + $this->TOC_even_header_value = $toc_ehvalue; + $this->TOC_odd_footer_value = $toc_ofvalue; + $this->TOC_even_footer_value = $toc_efvalue; + $this->TOC_page_selector = $toc_pagesel; + $this->TOC_resetpagenum = $toc_resetpagenum; // mPDF 6 + $this->TOC_pagenumstyle = $toc_pagenumstyle; // mPDF 6 + $this->TOC_suppress = $toc_suppress; // mPDF 6 + $this->TOCsheetsize = $toc_sheetsize; + } + } + + /** + * Initiate, and Mark a place for the Table of Contents to be inserted + */ + public function TOC( + $tocfont = '', + $tocfontsize = 0, + $tocindent = 0, + $resetpagenum = '', + $pagenumstyle = '', + $suppress = '', + $toc_orientation = '', + $TOCusePaging = true, + $TOCuseLinking = false, + $toc_id = 0, + $tocoutdent = '', + $toc_resetpagenum = '', + $toc_pagenumstyle = '', + $toc_suppress = '' + ) { + + if (strtoupper($toc_id) == 'ALL') { + $toc_id = '_mpdf_all'; + } elseif (!$toc_id) { + $toc_id = 0; + } else { + $toc_id = strtolower($toc_id); + } + // To use odd and even pages + // Cannot start table of contents on an even page + if (($this->mpdf->mirrorMargins) && (($this->mpdf->page) % 2 == 0)) { // EVEN + if ($this->mpdf->ColActive) { + if (count($this->mpdf->columnbuffer)) { + $this->mpdf->printcolumnbuffer(); + } + } + $this->mpdf->AddPage($this->mpdf->CurOrientation, '', $resetpagenum, $pagenumstyle, $suppress); + } else { + $this->mpdf->PageNumSubstitutions[] = ['from' => $this->mpdf->page, 'reset' => $resetpagenum, 'type' => $pagenumstyle, 'suppress' => $suppress]; + } + if ($toc_id) { + $this->m_TOC[$toc_id]['TOCmark'] = $this->mpdf->page; + $this->m_TOC[$toc_id]['TOCoutdent'] = $tocoutdent; + $this->m_TOC[$toc_id]['TOCorientation'] = $toc_orientation; + $this->m_TOC[$toc_id]['TOCuseLinking'] = $TOCuseLinking; + $this->m_TOC[$toc_id]['TOCusePaging'] = $TOCusePaging; + $this->m_TOC[$toc_id]['TOC_resetpagenum'] = $toc_resetpagenum; // mPDF 6 + $this->m_TOC[$toc_id]['TOC_pagenumstyle'] = $toc_pagenumstyle; // mPDF 6 + $this->m_TOC[$toc_id]['TOC_suppress'] = $toc_suppress; // mPDF 6 + } else { + $this->TOCmark = $this->mpdf->page; + $this->TOCoutdent = $tocoutdent; + $this->TOCorientation = $toc_orientation; + $this->TOCuseLinking = $TOCuseLinking; + $this->TOCusePaging = $TOCusePaging; + $this->TOC_resetpagenum = $toc_resetpagenum; // mPDF 6 + $this->TOC_pagenumstyle = $toc_pagenumstyle; // mPDF 6 + $this->TOC_suppress = $toc_suppress; // mPDF 6 + } + } + + public function insertTOC() + { + /* + * Fix the TOC page numbering problem + * + * To do this, the current class is deep cloned and then the TOC functionality run. The correct page + * numbers are calculated when the TOC pages are moved into position in the cloned object (see Mpdf::MovePages). + * It's then a matter of copying the correct page numbers to the original object and letting the TOC functionality + * run as per normal. + * + * See https://github.com/mpdf/mpdf/issues/642 + */ + if (!$this->tocTocPaintBegun) { + $copier = new DeepCopy(true); + $tocClassClone = $copier->copy($this); + $tocClassClone->beginTocPaint(); + $tocClassClone->insertTOC(); + $this->_toc = $tocClassClone->_toc; + } + + $notocs = 0; + if ($this->TOCmark) { + $notocs = 1; + } + $notocs += count($this->m_TOC); + + if ($notocs == 0) { + return; + } + + if (count($this->m_TOC)) { + reset($this->m_TOC); + } + $added_toc_pages = 0; + + if ($this->mpdf->ColActive) { + $this->mpdf->SetColumns(0); + } + if (($this->mpdf->mirrorMargins) && (($this->mpdf->page) % 2 == 1)) { // ODD + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $extrapage = true; + } else { + $extrapage = false; + } + + for ($toci = 0; $toci < $notocs; $toci++) { + if ($toci == 0 && $this->TOCmark) { + $toc_id = 0; + $toc_page = $this->TOCmark; + $tocoutdent = $this->TOCoutdent; + $toc_orientation = $this->TOCorientation; + $TOCuseLinking = $this->TOCuseLinking; + $TOCusePaging = $this->TOCusePaging; + $toc_preHTML = $this->TOCpreHTML; + $toc_postHTML = $this->TOCpostHTML; + $toc_bookmarkText = $this->TOCbookmarkText; + $toc_mgl = $this->TOC_margin_left; + $toc_mgr = $this->TOC_margin_right; + $toc_mgt = $this->TOC_margin_top; + $toc_mgb = $this->TOC_margin_bottom; + $toc_mgh = $this->TOC_margin_header; + $toc_mgf = $this->TOC_margin_footer; + $toc_ohname = $this->TOC_odd_header_name; + $toc_ehname = $this->TOC_even_header_name; + $toc_ofname = $this->TOC_odd_footer_name; + $toc_efname = $this->TOC_even_footer_name; + $toc_ohvalue = $this->TOC_odd_header_value; + $toc_ehvalue = $this->TOC_even_header_value; + $toc_ofvalue = $this->TOC_odd_footer_value; + $toc_efvalue = $this->TOC_even_footer_value; + $toc_page_selector = $this->TOC_page_selector; + $toc_resetpagenum = $this->TOC_resetpagenum; // mPDF 6 + $toc_pagenumstyle = $this->TOC_pagenumstyle; // mPDF 6 + $toc_suppress = $this->TOC_suppress; // mPDF 6 + $toc_sheet_size = (isset($this->TOCsheetsize) ? $this->TOCsheetsize : ''); + } else { + $arr = current($this->m_TOC); + + $toc_id = key($this->m_TOC); + $toc_page = $this->m_TOC[$toc_id]['TOCmark']; + $tocoutdent = $this->m_TOC[$toc_id]['TOCoutdent']; + $toc_orientation = $this->m_TOC[$toc_id]['TOCorientation']; + $TOCuseLinking = $this->m_TOC[$toc_id]['TOCuseLinking']; + $TOCusePaging = $this->m_TOC[$toc_id]['TOCusePaging']; + if (isset($this->m_TOC[$toc_id]['TOCpreHTML'])) { + $toc_preHTML = $this->m_TOC[$toc_id]['TOCpreHTML']; + } else { + $toc_preHTML = ''; + } + if (isset($this->m_TOC[$toc_id]['TOCpostHTML'])) { + $toc_postHTML = $this->m_TOC[$toc_id]['TOCpostHTML']; + } else { + $toc_postHTML = ''; + } + if (isset($this->m_TOC[$toc_id]['TOCbookmarkText'])) { + $toc_bookmarkText = $this->m_TOC[$toc_id]['TOCbookmarkText']; + } else { + $toc_bookmarkText = ''; + } // *BOOKMARKS* + $toc_mgl = $this->m_TOC[$toc_id]['TOC_margin_left']; + $toc_mgr = $this->m_TOC[$toc_id]['TOC_margin_right']; + $toc_mgt = $this->m_TOC[$toc_id]['TOC_margin_top']; + $toc_mgb = $this->m_TOC[$toc_id]['TOC_margin_bottom']; + $toc_mgh = $this->m_TOC[$toc_id]['TOC_margin_header']; + $toc_mgf = $this->m_TOC[$toc_id]['TOC_margin_footer']; + $toc_ohname = $this->m_TOC[$toc_id]['TOC_odd_header_name']; + $toc_ehname = $this->m_TOC[$toc_id]['TOC_even_header_name']; + $toc_ofname = $this->m_TOC[$toc_id]['TOC_odd_footer_name']; + $toc_efname = $this->m_TOC[$toc_id]['TOC_even_footer_name']; + $toc_ohvalue = $this->m_TOC[$toc_id]['TOC_odd_header_value']; + $toc_ehvalue = $this->m_TOC[$toc_id]['TOC_even_header_value']; + $toc_ofvalue = $this->m_TOC[$toc_id]['TOC_odd_footer_value']; + $toc_efvalue = $this->m_TOC[$toc_id]['TOC_even_footer_value']; + $toc_page_selector = $this->m_TOC[$toc_id]['TOC_page_selector']; + $toc_resetpagenum = $this->m_TOC[$toc_id]['TOC_resetpagenum']; // mPDF 6 + $toc_pagenumstyle = $this->m_TOC[$toc_id]['TOC_pagenumstyle']; // mPDF 6 + $toc_suppress = $this->m_TOC[$toc_id]['TOC_suppress']; // mPDF 6 + $toc_sheet_size = (isset($this->m_TOC[$toc_id]['TOCsheetsize']) ? $this->m_TOC[$toc_id]['TOCsheetsize'] : ''); + next($this->m_TOC); + } + + // mPDF 5.6.31 + if (!$toc_orientation) { + $toc_orientation = $this->mpdf->DefOrientation; + } + + // mPDF 6 number style and suppress now picked up from section preceding ToC + list($tp_pagenumstyle, $tp_suppress, $tp_reset) = $this->mpdf->docPageSettings($toc_page - 1); + + if ($toc_resetpagenum) { + $tp_reset = $toc_resetpagenum; // mPDF 6 + } + if ($toc_pagenumstyle) { + $tp_pagenumstyle = $toc_pagenumstyle; // mPDF 6 + } + if ($toc_suppress || $toc_suppress === '0') { + $tp_suppress = $toc_suppress; // mPDF 6 + } + + $this->mpdf->AddPage($toc_orientation, '', $tp_reset, $tp_pagenumstyle, $tp_suppress, $toc_mgl, $toc_mgr, $toc_mgt, $toc_mgb, $toc_mgh, $toc_mgf, $toc_ohname, $toc_ehname, $toc_ofname, $toc_efname, $toc_ohvalue, $toc_ehvalue, $toc_ofvalue, $toc_efvalue, $toc_page_selector, $toc_sheet_size); // mPDF 6 + + $this->mpdf->writingToC = true; // mPDF 5.6.38 + + /* + * Ensure the TOC Page Number Style doesn't effect the TOC Numbering (added automatically in `AddPage()` above) + * Ensure the page numbers show in the TOC when the 'suppress' setting is enabled + * @see https://github.com/mpdf/mpdf/issues/792 + * @see https://github.com/mpdf/mpdf/issues/777 + */ + if (isset($tocClassClone)) { + $this->mpdf->PageNumSubstitutions = array_map(function ($sub) { + $sub['suppress'] = ''; + return $sub; + }, $tocClassClone->mpdf->PageNumSubstitutions); + } + + // mPDF 5.6.31 + $tocstart = count($this->mpdf->pages); + if (isset($toc_preHTML) && $toc_preHTML) { + $this->mpdf->WriteHTML($toc_preHTML); + } + + // mPDF 5.6.19 + $html = '<div class="mpdf_toc" id="mpdf_toc_' . $toc_id . '">'; + foreach ($this->_toc as $t) { + if ($t['toc_id'] === '_mpdf_all' || $t['toc_id'] === $toc_id) { + $html .= '<div class="mpdf_toc_level_' . $t['l'] . '">'; + if ($TOCuseLinking) { + $html .= '<a class="mpdf_toc_a" href="#__mpdfinternallink_' . $t['link'] . '">'; + } + $html .= '<span class="mpdf_toc_t_level_' . $t['l'] . '">' . $t['t'] . '</span>'; + if ($TOCuseLinking) { + $html .= '</a>'; + } + if (!$tocoutdent) { + $tocoutdent = '0'; + } + if ($TOCusePaging) { + $html .= ' <dottab outdent="' . $tocoutdent . '" /> '; + if ($TOCuseLinking) { + $html .= '<a class="mpdf_toc_a" href="#__mpdfinternallink_' . $t['link'] . '">'; + } + $html .= '<span class="mpdf_toc_p_level_' . $t['l'] . '">' . $this->mpdf->docPageNum($t['p']) . '</span>'; + if ($TOCuseLinking) { + $html .= '</a>'; + } + } + $html .= '</div>'; + } + } + $html .= '</div>'; + $this->mpdf->WriteHTML($html); + + if (isset($toc_postHTML) && $toc_postHTML) { + $this->mpdf->WriteHTML($toc_postHTML); + } + $this->mpdf->writingToC = false; // mPDF 5.6.38 + $this->mpdf->AddPage($toc_orientation, 'E'); + + $n_toc = $this->mpdf->page - $tocstart + 1; + + if ($toci == 0 && $this->TOCmark) { + $TOC_start = $tocstart; + $TOC_end = $this->mpdf->page; + $TOC_npages = $n_toc; + } else { + $this->m_TOC[$toc_id]['start'] = $tocstart; + $this->m_TOC[$toc_id]['end'] = $this->mpdf->page; + $this->m_TOC[$toc_id]['npages'] = $n_toc; + } + } + + $s = ''; + + $s .= $this->mpdf->PrintBodyBackgrounds(); + + $s .= $this->mpdf->PrintPageBackgrounds(); + $this->mpdf->pages[$this->mpdf->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', "\n" . $s . "\n" . '\\1', $this->mpdf->pages[$this->mpdf->page]); + $this->mpdf->pageBackgrounds = []; + + //Page footer + $this->mpdf->InFooter = true; + $this->mpdf->Footer(); + $this->mpdf->InFooter = false; + + // 2nd time through to move pages etc. + $added_toc_pages = 0; + if (count($this->m_TOC)) { + reset($this->m_TOC); + } + + for ($toci = 0; $toci < $notocs; $toci++) { + if ($toci == 0 && $this->TOCmark) { + $toc_id = 0; + $toc_page = $this->TOCmark + $added_toc_pages; + $toc_orientation = $this->TOCorientation; + $TOCuseLinking = $this->TOCuseLinking; + $TOCusePaging = $this->TOCusePaging; + $toc_bookmarkText = $this->TOCbookmarkText; // *BOOKMARKS* + + $tocstart = $TOC_start; + $tocend = $n = $TOC_end; + $n_toc = $TOC_npages; + } else { + $arr = current($this->m_TOC); + + $toc_id = key($this->m_TOC); + $toc_page = $this->m_TOC[$toc_id]['TOCmark'] + $added_toc_pages; + $toc_orientation = $this->m_TOC[$toc_id]['TOCorientation']; + $TOCuseLinking = $this->m_TOC[$toc_id]['TOCuseLinking']; + $TOCusePaging = $this->m_TOC[$toc_id]['TOCusePaging']; + $toc_bookmarkText = Arrays::get($this->m_TOC[$toc_id], 'TOCbookmarkText', null); // *BOOKMARKS* + + $tocstart = $this->m_TOC[$toc_id]['start']; + $tocend = $n = $this->m_TOC[$toc_id]['end']; + $n_toc = $this->m_TOC[$toc_id]['npages']; + + next($this->m_TOC); + } + + // Now pages moved + $added_toc_pages += $n_toc; + + $this->mpdf->MovePages($toc_page, $tocstart, $tocend); + $this->mpdf->pgsIns[$toc_page] = $tocend - $tocstart + 1; + + /* -- BOOKMARKS -- */ + // Insert new Bookmark for Bookmark + if ($toc_bookmarkText) { + $insert = -1; + foreach ($this->mpdf->BMoutlines as $i => $o) { + if ($o['p'] < $toc_page) { // i.e. before point of insertion + $insert = $i; + } + } + $txt = $this->mpdf->purify_utf8_text($toc_bookmarkText); + if ($this->mpdf->text_input_as_HTML) { + $txt = $this->mpdf->all_entities_to_utf8($txt); + } + $newBookmark[0] = ['t' => $txt, 'l' => 0, 'y' => 0, 'p' => $toc_page]; + array_splice($this->mpdf->BMoutlines, ($insert + 1), 0, $newBookmark); + } + /* -- END BOOKMARKS -- */ + } + + // Delete empty page that was inserted earlier + if ($extrapage) { + unset($this->mpdf->pages[count($this->mpdf->pages)]); + $this->mpdf->page--; // Reset page pointer + } + + /* Fix the over adjustment of the TOC and Page Substitutions values */ + if (isset($tocClassClone)) { + $this->_toc = $tocClassClone->_toc; + $this->mpdf->PageNumSubstitutions = $tocClassClone->mpdf->PageNumSubstitutions; + unset($tocClassClone); + } + } + + public function openTagTOC($attr) + { + if (isset($attr['OUTDENT']) && $attr['OUTDENT']) { + $tocoutdent = $attr['OUTDENT']; + } else { + $tocoutdent = ''; + } // mPDF 5.6.19 + if (isset($attr['RESETPAGENUM']) && $attr['RESETPAGENUM']) { + $resetpagenum = $attr['RESETPAGENUM']; + } else { + $resetpagenum = ''; + } + if (isset($attr['PAGENUMSTYLE']) && $attr['PAGENUMSTYLE']) { + $pagenumstyle = $attr['PAGENUMSTYLE']; + } else { + $pagenumstyle = ''; + } + if (isset($attr['SUPPRESS']) && $attr['SUPPRESS']) { + $suppress = $attr['SUPPRESS']; + } else { + $suppress = ''; + } + if (isset($attr['TOC-ORIENTATION']) && $attr['TOC-ORIENTATION']) { + $toc_orientation = $attr['TOC-ORIENTATION']; + } else { + $toc_orientation = ''; + } + if (isset($attr['PAGING']) && (strtoupper($attr['PAGING']) == 'OFF' || $attr['PAGING'] === '0')) { + $paging = false; + } else { + $paging = true; + } + if (isset($attr['LINKS']) && (strtoupper($attr['LINKS']) == 'ON' || $attr['LINKS'] == 1)) { + $links = true; + } else { + $links = false; + } + if (isset($attr['NAME']) && $attr['NAME']) { + $toc_id = strtolower($attr['NAME']); + } else { + $toc_id = 0; + } + $this->TOC('', 0, 0, $resetpagenum, $pagenumstyle, $suppress, $toc_orientation, $paging, $links, $toc_id, $tocoutdent); // mPDF 5.6.19 5.6.31 + } + + public function openTagTOCPAGEBREAK($attr) + { + if (isset($attr['NAME']) && $attr['NAME']) { + $toc_id = strtolower($attr['NAME']); + } else { + $toc_id = 0; + } + if ($toc_id) { + if (isset($attr['OUTDENT']) && $attr['OUTDENT']) { + $this->m_TOC[$toc_id]['TOCoutdent'] = $attr['OUTDENT']; + } else { + $this->m_TOC[$toc_id]['TOCoutdent'] = ''; + } // mPDF 5.6.19 + if (isset($attr['TOC-ORIENTATION']) && $attr['TOC-ORIENTATION']) { + $this->m_TOC[$toc_id]['TOCorientation'] = $attr['TOC-ORIENTATION']; + } else { + $this->m_TOC[$toc_id]['TOCorientation'] = ''; + } + if (isset($attr['PAGING']) && (strtoupper($attr['PAGING']) == 'OFF' || $attr['PAGING'] === '0')) { + $this->m_TOC[$toc_id]['TOCusePaging'] = false; + } else { + $this->m_TOC[$toc_id]['TOCusePaging'] = true; + } + if (isset($attr['LINKS']) && (strtoupper($attr['LINKS']) == 'ON' || $attr['LINKS'] == 1)) { + $this->m_TOC[$toc_id]['TOCuseLinking'] = true; + } else { + $this->m_TOC[$toc_id]['TOCuseLinking'] = false; + } + + $this->m_TOC[$toc_id]['TOC_margin_left'] = $this->m_TOC[$toc_id]['TOC_margin_right'] = $this->m_TOC[$toc_id]['TOC_margin_top'] = $this->m_TOC[$toc_id]['TOC_margin_bottom'] = $this->m_TOC[$toc_id]['TOC_margin_header'] = $this->m_TOC[$toc_id]['TOC_margin_footer'] = ''; + if (isset($attr['TOC-MARGIN-RIGHT'])) { + $this->m_TOC[$toc_id]['TOC_margin_right'] = $this->sizeConverter->convert($attr['TOC-MARGIN-RIGHT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-LEFT'])) { + $this->m_TOC[$toc_id]['TOC_margin_left'] = $this->sizeConverter->convert($attr['TOC-MARGIN-LEFT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-TOP'])) { + $this->m_TOC[$toc_id]['TOC_margin_top'] = $this->sizeConverter->convert($attr['TOC-MARGIN-TOP'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-BOTTOM'])) { + $this->m_TOC[$toc_id]['TOC_margin_bottom'] = $this->sizeConverter->convert($attr['TOC-MARGIN-BOTTOM'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-HEADER'])) { + $this->m_TOC[$toc_id]['TOC_margin_header'] = $this->sizeConverter->convert($attr['TOC-MARGIN-HEADER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-FOOTER'])) { + $this->m_TOC[$toc_id]['TOC_margin_footer'] = $this->sizeConverter->convert($attr['TOC-MARGIN-FOOTER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + $this->m_TOC[$toc_id]['TOC_odd_header_name'] = $this->m_TOC[$toc_id]['TOC_even_header_name'] = $this->m_TOC[$toc_id]['TOC_odd_footer_name'] = $this->m_TOC[$toc_id]['TOC_even_footer_name'] = ''; + if (isset($attr['TOC-ODD-HEADER-NAME']) && $attr['TOC-ODD-HEADER-NAME']) { + $this->m_TOC[$toc_id]['TOC_odd_header_name'] = $attr['TOC-ODD-HEADER-NAME']; + } + if (isset($attr['TOC-EVEN-HEADER-NAME']) && $attr['TOC-EVEN-HEADER-NAME']) { + $this->m_TOC[$toc_id]['TOC_even_header_name'] = $attr['TOC-EVEN-HEADER-NAME']; + } + if (isset($attr['TOC-ODD-FOOTER-NAME']) && $attr['TOC-ODD-FOOTER-NAME']) { + $this->m_TOC[$toc_id]['TOC_odd_footer_name'] = $attr['TOC-ODD-FOOTER-NAME']; + } + if (isset($attr['TOC-EVEN-FOOTER-NAME']) && $attr['TOC-EVEN-FOOTER-NAME']) { + $this->m_TOC[$toc_id]['TOC_even_footer_name'] = $attr['TOC-EVEN-FOOTER-NAME']; + } + $this->m_TOC[$toc_id]['TOC_odd_header_value'] = $this->m_TOC[$toc_id]['TOC_even_header_value'] = $this->m_TOC[$toc_id]['TOC_odd_footer_value'] = $this->m_TOC[$toc_id]['TOC_even_footer_value'] = 0; + if (isset($attr['TOC-ODD-HEADER-VALUE']) && ($attr['TOC-ODD-HEADER-VALUE'] == '1' || strtoupper($attr['TOC-ODD-HEADER-VALUE']) == 'ON')) { + $this->m_TOC[$toc_id]['TOC_odd_header_value'] = 1; + } elseif (isset($attr['TOC-ODD-HEADER-VALUE']) && ($attr['TOC-ODD-HEADER-VALUE'] == '-1' || strtoupper($attr['TOC-ODD-HEADER-VALUE']) == 'OFF')) { + $this->m_TOC[$toc_id]['TOC_odd_header_value'] = -1; + } + if (isset($attr['TOC-EVEN-HEADER-VALUE']) && ($attr['TOC-EVEN-HEADER-VALUE'] == '1' || strtoupper($attr['TOC-EVEN-HEADER-VALUE']) == 'ON')) { + $this->m_TOC[$toc_id]['TOC_even_header_value'] = 1; + } elseif (isset($attr['TOC-EVEN-HEADER-VALUE']) && ($attr['TOC-EVEN-HEADER-VALUE'] == '-1' || strtoupper($attr['TOC-EVEN-HEADER-VALUE']) == 'OFF')) { + $this->m_TOC[$toc_id]['TOC_even_header_value'] = -1; + } + if (isset($attr['TOC-ODD-FOOTER-VALUE']) && ($attr['TOC-ODD-FOOTER-VALUE'] == '1' || strtoupper($attr['TOC-ODD-FOOTER-VALUE']) == 'ON')) { + $this->m_TOC[$toc_id]['TOC_odd_footer_value'] = 1; + } elseif (isset($attr['TOC-ODD-FOOTER-VALUE']) && ($attr['TOC-ODD-FOOTER-VALUE'] == '-1' || strtoupper($attr['TOC-ODD-FOOTER-VALUE']) == 'OFF')) { + $this->m_TOC[$toc_id]['TOC_odd_footer_value'] = -1; + } + if (isset($attr['TOC-EVEN-FOOTER-VALUE']) && ($attr['TOC-EVEN-FOOTER-VALUE'] == '1' || strtoupper($attr['TOC-EVEN-FOOTER-VALUE']) == 'ON')) { + $this->m_TOC[$toc_id]['TOC_even_footer_value'] = 1; + } elseif (isset($attr['TOC-EVEN-FOOTER-VALUE']) && ($attr['TOC-EVEN-FOOTER-VALUE'] == '-1' || strtoupper($attr['TOC-EVEN-FOOTER-VALUE']) == 'OFF')) { + $this->m_TOC[$toc_id]['TOC_even_footer_value'] = -1; + } + if (isset($attr['TOC-RESETPAGENUM']) && $attr['TOC-RESETPAGENUM']) { + $this->m_TOC[$toc_id]['TOC_resetpagenum'] = $attr['TOC-RESETPAGENUM']; + } else { + $this->m_TOC[$toc_id]['TOC_resetpagenum'] = ''; + } // mPDF 6 + if (isset($attr['TOC-PAGENUMSTYLE']) && $attr['TOC-PAGENUMSTYLE']) { + $this->m_TOC[$toc_id]['TOC_pagenumstyle'] = $attr['TOC-PAGENUMSTYLE']; + } else { + $this->m_TOC[$toc_id]['TOC_pagenumstyle'] = ''; + } // mPDF 6 + if (isset($attr['TOC-SUPPRESS']) && ($attr['TOC-SUPPRESS'] || $attr['TOC-SUPPRESS'] === '0')) { + $this->m_TOC[$toc_id]['TOC_suppress'] = $attr['TOC-SUPPRESS']; + } else { + $this->m_TOC[$toc_id]['TOC_suppress'] = ''; + } // mPDF 6 + if (isset($attr['TOC-PAGE-SELECTOR']) && $attr['TOC-PAGE-SELECTOR']) { + $this->m_TOC[$toc_id]['TOC_page_selector'] = $attr['TOC-PAGE-SELECTOR']; + } else { + $this->m_TOC[$toc_id]['TOC_page_selector'] = ''; + } + if (isset($attr['TOC-SHEET-SIZE']) && $attr['TOC-SHEET-SIZE']) { + $this->m_TOC[$toc_id]['TOCsheetsize'] = $attr['TOC-SHEET-SIZE']; + } else { + $this->m_TOC[$toc_id]['TOCsheetsize'] = ''; + } + + + if (isset($attr['TOC-PREHTML']) && $attr['TOC-PREHTML']) { + $this->m_TOC[$toc_id]['TOCpreHTML'] = htmlspecialchars_decode($attr['TOC-PREHTML'], ENT_QUOTES); + } + if (isset($attr['TOC-POSTHTML']) && $attr['TOC-POSTHTML']) { + $this->m_TOC[$toc_id]['TOCpostHTML'] = htmlspecialchars_decode($attr['TOC-POSTHTML'], ENT_QUOTES); + } + + if (isset($attr['TOC-BOOKMARKTEXT']) && $attr['TOC-BOOKMARKTEXT']) { + $this->m_TOC[$toc_id]['TOCbookmarkText'] = htmlspecialchars_decode($attr['TOC-BOOKMARKTEXT'], ENT_QUOTES); + } // *BOOKMARKS* + } else { + if (isset($attr['OUTDENT']) && $attr['OUTDENT']) { + $this->TOCoutdent = $attr['OUTDENT']; + } else { + $this->TOCoutdent = ''; + } // mPDF 5.6.19 + if (isset($attr['TOC-ORIENTATION']) && $attr['TOC-ORIENTATION']) { + $this->TOCorientation = $attr['TOC-ORIENTATION']; + } else { + $this->TOCorientation = ''; + } + if (isset($attr['PAGING']) && (strtoupper($attr['PAGING']) == 'OFF' || $attr['PAGING'] === '0')) { + $this->TOCusePaging = false; + } else { + $this->TOCusePaging = true; + } + if (isset($attr['LINKS']) && (strtoupper($attr['LINKS']) == 'ON' || $attr['LINKS'] == 1)) { + $this->TOCuseLinking = true; + } else { + $this->TOCuseLinking = false; + } + + $this->TOC_margin_left = $this->TOC_margin_right = $this->TOC_margin_top = $this->TOC_margin_bottom = $this->TOC_margin_header = $this->TOC_margin_footer = ''; + if (isset($attr['TOC-MARGIN-RIGHT'])) { + $this->TOC_margin_right = $this->sizeConverter->convert($attr['TOC-MARGIN-RIGHT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-LEFT'])) { + $this->TOC_margin_left = $this->sizeConverter->convert($attr['TOC-MARGIN-LEFT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-TOP'])) { + $this->TOC_margin_top = $this->sizeConverter->convert($attr['TOC-MARGIN-TOP'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-BOTTOM'])) { + $this->TOC_margin_bottom = $this->sizeConverter->convert($attr['TOC-MARGIN-BOTTOM'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-HEADER'])) { + $this->TOC_margin_header = $this->sizeConverter->convert($attr['TOC-MARGIN-HEADER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['TOC-MARGIN-FOOTER'])) { + $this->TOC_margin_footer = $this->sizeConverter->convert($attr['TOC-MARGIN-FOOTER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + $this->TOC_odd_header_name = $this->TOC_even_header_name = $this->TOC_odd_footer_name = $this->TOC_even_footer_name = ''; + if (isset($attr['TOC-ODD-HEADER-NAME']) && $attr['TOC-ODD-HEADER-NAME']) { + $this->TOC_odd_header_name = $attr['TOC-ODD-HEADER-NAME']; + } + if (isset($attr['TOC-EVEN-HEADER-NAME']) && $attr['TOC-EVEN-HEADER-NAME']) { + $this->TOC_even_header_name = $attr['TOC-EVEN-HEADER-NAME']; + } + if (isset($attr['TOC-ODD-FOOTER-NAME']) && $attr['TOC-ODD-FOOTER-NAME']) { + $this->TOC_odd_footer_name = $attr['TOC-ODD-FOOTER-NAME']; + } + if (isset($attr['TOC-EVEN-FOOTER-NAME']) && $attr['TOC-EVEN-FOOTER-NAME']) { + $this->TOC_even_footer_name = $attr['TOC-EVEN-FOOTER-NAME']; + } + $this->TOC_odd_header_value = $this->TOC_even_header_value = $this->TOC_odd_footer_value = $this->TOC_even_footer_value = 0; + if (isset($attr['TOC-ODD-HEADER-VALUE']) && ($attr['TOC-ODD-HEADER-VALUE'] == '1' || strtoupper($attr['TOC-ODD-HEADER-VALUE']) == 'ON')) { + $this->TOC_odd_header_value = 1; + } elseif (isset($attr['TOC-ODD-HEADER-VALUE']) && ($attr['TOC-ODD-HEADER-VALUE'] == '-1' || strtoupper($attr['TOC-ODD-HEADER-VALUE']) == 'OFF')) { + $this->TOC_odd_header_value = -1; + } + if (isset($attr['TOC-EVEN-HEADER-VALUE']) && ($attr['TOC-EVEN-HEADER-VALUE'] == '1' || strtoupper($attr['TOC-EVEN-HEADER-VALUE']) == 'ON')) { + $this->TOC_even_header_value = 1; + } elseif (isset($attr['TOC-EVEN-HEADER-VALUE']) && ($attr['TOC-EVEN-HEADER-VALUE'] == '-1' || strtoupper($attr['TOC-EVEN-HEADER-VALUE']) == 'OFF')) { + $this->TOC_even_header_value = -1; + } + + if (isset($attr['TOC-ODD-FOOTER-VALUE']) && ($attr['TOC-ODD-FOOTER-VALUE'] == '1' || strtoupper($attr['TOC-ODD-FOOTER-VALUE']) == 'ON')) { + $this->TOC_odd_footer_value = 1; + } elseif (isset($attr['TOC-ODD-FOOTER-VALUE']) && ($attr['TOC-ODD-FOOTER-VALUE'] == '-1' || strtoupper($attr['TOC-ODD-FOOTER-VALUE']) == 'OFF')) { + $this->TOC_odd_footer_value = -1; + } + if (isset($attr['TOC-EVEN-FOOTER-VALUE']) && ($attr['TOC-EVEN-FOOTER-VALUE'] == '1' || strtoupper($attr['TOC-EVEN-FOOTER-VALUE']) == 'ON')) { + $this->TOC_even_footer_value = 1; + } elseif (isset($attr['TOC-EVEN-FOOTER-VALUE']) && ($attr['TOC-EVEN-FOOTER-VALUE'] == '-1' || strtoupper($attr['TOC-EVEN-FOOTER-VALUE']) == 'OFF')) { + $this->TOC_even_footer_value = -1; + } + if (isset($attr['TOC-PAGE-SELECTOR']) && $attr['TOC-PAGE-SELECTOR']) { + $this->TOC_page_selector = $attr['TOC-PAGE-SELECTOR']; + } else { + $this->TOC_page_selector = ''; + } + if (isset($attr['TOC-RESETPAGENUM']) && $attr['TOC-RESETPAGENUM']) { + $this->TOC_resetpagenum = $attr['TOC-RESETPAGENUM']; + } else { + $this->TOC_resetpagenum = ''; + } // mPDF 6 + if (isset($attr['TOC-PAGENUMSTYLE']) && $attr['TOC-PAGENUMSTYLE']) { + $this->TOC_pagenumstyle = $attr['TOC-PAGENUMSTYLE']; + } else { + $this->TOC_pagenumstyle = ''; + } // mPDF 6 + if (isset($attr['TOC-SUPPRESS']) && ($attr['TOC-SUPPRESS'] || $attr['TOC-SUPPRESS'] === '0')) { + $this->TOC_suppress = $attr['TOC-SUPPRESS']; + } else { + $this->TOC_suppress = ''; + } // mPDF 6 + if (isset($attr['TOC-SHEET-SIZE']) && $attr['TOC-SHEET-SIZE']) { + $this->TOCsheetsize = $attr['TOC-SHEET-SIZE']; + } else { + $this->TOCsheetsize = ''; + } + + if (isset($attr['TOC-PREHTML']) && $attr['TOC-PREHTML']) { + $this->TOCpreHTML = htmlspecialchars_decode($attr['TOC-PREHTML'], ENT_QUOTES); + } + if (isset($attr['TOC-POSTHTML']) && $attr['TOC-POSTHTML']) { + $this->TOCpostHTML = htmlspecialchars_decode($attr['TOC-POSTHTML'], ENT_QUOTES); + } + if (isset($attr['TOC-BOOKMARKTEXT']) && $attr['TOC-BOOKMARKTEXT']) { + $this->TOCbookmarkText = htmlspecialchars_decode($attr['TOC-BOOKMARKTEXT'], ENT_QUOTES); + } + } + + if ($this->mpdf->y == $this->mpdf->tMargin && (!$this->mpdf->mirrorMargins || ($this->mpdf->mirrorMargins && $this->mpdf->page % 2 == 1))) { + if ($toc_id) { + $this->m_TOC[$toc_id]['TOCmark'] = $this->mpdf->page; + } else { + $this->TOCmark = $this->mpdf->page; + } + // Don't add a page + if ($this->mpdf->page == 1 && count($this->mpdf->PageNumSubstitutions) == 0) { + $resetpagenum = ''; + $pagenumstyle = ''; + $suppress = ''; + if (isset($attr['RESETPAGENUM'])) { + $resetpagenum = $attr['RESETPAGENUM']; + } + if (isset($attr['PAGENUMSTYLE'])) { + $pagenumstyle = $attr['PAGENUMSTYLE']; + } + if (isset($attr['SUPPRESS'])) { + $suppress = $attr['SUPPRESS']; + } + if (!$suppress) { + $suppress = 'off'; + } + $this->mpdf->PageNumSubstitutions[] = ['from' => 1, 'reset' => $resetpagenum, 'type' => $pagenumstyle, 'suppress' => $suppress]; + } + return [true, $toc_id]; + } + + // No break - continues as PAGEBREAK... + return [false, $toc_id]; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag.php b/src/vendor/mpdf/mpdf/src/Tag.php new file mode 100644 index 000000000..33d90b6b7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag.php @@ -0,0 +1,250 @@ +<?php + +namespace Mpdf; + +use Mpdf\Strict; +use Mpdf\Color\ColorConverter; +use Mpdf\Image\ImageProcessor; +use Mpdf\Language\LanguageToFontInterface; + +class Tag +{ + + use Strict; + + /** + * @var \Mpdf\Mpdf + */ + private $mpdf; + + /** + * @var \Mpdf\Cache + */ + private $cache; + + /** + * @var \Mpdf\CssManager + */ + private $cssManager; + + /** + * @var \Mpdf\Form + */ + private $form; + + /** + * @var \Mpdf\Otl + */ + private $otl; + + /** + * @var \Mpdf\TableOfContents + */ + private $tableOfContents; + + /** + * @var \Mpdf\SizeConverter + */ + private $sizeConverter; + + /** + * @var \Mpdf\Color\ColorConverter + */ + private $colorConverter; + + /** + * @var \Mpdf\Image\ImageProcessor + */ + private $imageProcessor; + + /** + * @var \Mpdf\Language\LanguageToFontInterface + */ + private $languageToFont; + + /** + * @param \Mpdf\Mpdf $mpdf + * @param \Mpdf\Cache $cache + * @param \Mpdf\CssManager $cssManager + * @param \Mpdf\Form $form + * @param \Mpdf\Otl $otl + * @param \Mpdf\TableOfContents $tableOfContents + * @param \Mpdf\SizeConverter $sizeConverter + * @param \Mpdf\Color\ColorConverter $colorConverter + * @param \Mpdf\Image\ImageProcessor $imageProcessor + * @param \Mpdf\Language\LanguageToFontInterface $languageToFont + */ + public function __construct( + Mpdf $mpdf, + Cache $cache, + CssManager $cssManager, + Form $form, + Otl $otl, + TableOfContents $tableOfContents, + SizeConverter $sizeConverter, + ColorConverter $colorConverter, + ImageProcessor $imageProcessor, + LanguageToFontInterface $languageToFont + ) { + + $this->mpdf = $mpdf; + $this->cache = $cache; + $this->cssManager = $cssManager; + $this->form = $form; + $this->otl = $otl; + $this->tableOfContents = $tableOfContents; + $this->sizeConverter = $sizeConverter; + $this->colorConverter = $colorConverter; + $this->imageProcessor = $imageProcessor; + $this->languageToFont = $languageToFont; + } + + /** + * @param string $tag The tag name + * @return \Mpdf\Tag\Tag + */ + private function getTagInstance($tag) + { + $className = self::getTagClassName($tag); + if (class_exists($className)) { + return new $className( + $this->mpdf, + $this->cache, + $this->cssManager, + $this->form, + $this->otl, + $this->tableOfContents, + $this->sizeConverter, + $this->colorConverter, + $this->imageProcessor, + $this->languageToFont + ); + } + } + + /** + * Returns the fully qualified name of the class handling the rendering of the given tag + * + * @param string $tag The tag name + * @return string The fully qualified name + */ + public static function getTagClassName($tag) + { + static $map = [ + 'BARCODE' => 'BarCode', + 'BLOCKQUOTE' => 'BlockQuote', + 'COLUMN_BREAK' => 'ColumnBreak', + 'COLUMNBREAK' => 'ColumnBreak', + 'DOTTAB' => 'DotTab', + 'FIELDSET' => 'FieldSet', + 'FIGCAPTION' => 'FigCaption', + 'FORMFEED' => 'FormFeed', + 'HGROUP' => 'HGroup', + 'INDEXENTRY' => 'IndexEntry', + 'INDEXINSERT' => 'IndexInsert', + 'NEWCOLUMN' => 'NewColumn', + 'NEWPAGE' => 'NewPage', + 'PAGEFOOTER' => 'PageFooter', + 'PAGEHEADER' => 'PageHeader', + 'PAGE_BREAK' => 'PageBreak', + 'PAGEBREAK' => 'PageBreak', + 'SETHTMLPAGEFOOTER' => 'SetHtmlPageFooter', + 'SETHTMLPAGEHEADER' => 'SetHtmlPageHeader', + 'SETPAGEFOOTER' => 'SetPageFooter', + 'SETPAGEHEADER' => 'SetPageHeader', + 'TBODY' => 'TBody', + 'TFOOT' => 'TFoot', + 'THEAD' => 'THead', + 'TEXTAREA' => 'TextArea', + 'TEXTCIRCLE' => 'TextCircle', + 'TOCENTRY' => 'TocEntry', + 'TOCPAGEBREAK' => 'TocPageBreak', + 'VAR' => 'VarTag', + 'WATERMARKIMAGE' => 'WatermarkImage', + 'WATERMARKTEXT' => 'WatermarkText', + ]; + + $className = 'Mpdf\Tag\\'; + $className .= isset($map[$tag]) ? $map[$tag] : ucfirst(strtolower($tag)); + + return $className; + } + + public function OpenTag($tag, $attr, &$ahtml, &$ihtml) + { + // Correct for tags where HTML5 specifies optional end tags excluding table elements (cf WriteHTML() ) + if ($this->mpdf->allow_html_optional_endtags) { + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['tag'])) { + $closed = false; + // li end tag may be omitted if immediately followed by another li element + if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'LI' && $tag == 'LI') { + $this->CloseTag('LI', $ahtml, $ihtml); + $closed = true; + } + // dt end tag may be omitted if immediately followed by another dt element or a dd element + if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'DT' && ($tag == 'DT' || $tag == 'DD')) { + $this->CloseTag('DT', $ahtml, $ihtml); + $closed = true; + } + // dd end tag may be omitted if immediately followed by another dd element or a dt element + if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'DD' && ($tag == 'DT' || $tag == 'DD')) { + $this->CloseTag('DD', $ahtml, $ihtml); + $closed = true; + } + // p end tag may be omitted if immediately followed by an address, article, aside, blockquote, div, dl, + // fieldset, form, h1, h2, h3, h4, h5, h6, hgroup, hr, main, nav, ol, p, pre, section, table, ul + if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'P' + && ($tag == 'P' || $tag == 'DIV' || $tag == 'H1' || $tag == 'H2' || $tag == 'H3' + || $tag == 'H4' || $tag == 'H5' || $tag == 'H6' || $tag == 'UL' || $tag == 'OL' + || $tag == 'TABLE' || $tag == 'PRE' || $tag == 'FORM' || $tag == 'ADDRESS' || $tag == 'BLOCKQUOTE' + || $tag == 'CENTER' || $tag == 'DL' || $tag == 'HR' || $tag == 'ARTICLE' || $tag == 'ASIDE' + || $tag == 'FIELDSET' || $tag == 'HGROUP' || $tag == 'MAIN' || $tag == 'NAV' || $tag == 'SECTION')) { + $this->CloseTag('P', $ahtml, $ihtml); + $closed = true; + } + // option end tag may be omitted if immediately followed by another option element + // (or if it is immediately followed by an optgroup element) + if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'OPTION' && $tag == 'OPTION') { + $this->CloseTag('OPTION', $ahtml, $ihtml); + $closed = true; + } + // Table elements - see also WriteHTML() + if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->mpdf->lastoptionaltag == 'TD') { + $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); + $closed = true; + } // *TABLES* + if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->mpdf->lastoptionaltag == 'TH') { + $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); + $closed = true; + } // *TABLES* + if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TR') { + $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); + $closed = true; + } // *TABLES* + if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TD') { + $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); + $this->CloseTag('TR', $ahtml, $ihtml); + $this->CloseTag('THEAD', $ahtml, $ihtml); + $closed = true; + } // *TABLES* + if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TH') { + $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); + $this->CloseTag('TR', $ahtml, $ihtml); + $this->CloseTag('THEAD', $ahtml, $ihtml); + $closed = true; + } // *TABLES* + } + } + + if ($object = $this->getTagInstance($tag)) { + return $object->open($attr, $ahtml, $ihtml); + } + } + + public function CloseTag($tag, &$ahtml, &$ihtml) + { + if ($object = $this->getTagInstance($tag)) { + return $object->close($ahtml, $ihtml); + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/A.php b/src/vendor/mpdf/mpdf/src/Tag/A.php new file mode 100644 index 000000000..0853b239b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/A.php @@ -0,0 +1,52 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class A extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + if (isset($attr['NAME']) && $attr['NAME'] != '') { + $e = ''; + /* -- BOOKMARKS -- */ + if ($this->mpdf->anchor2Bookmark) { + $objattr = []; + $objattr['CONTENT'] = htmlspecialchars_decode($attr['NAME'], ENT_QUOTES); + $objattr['type'] = 'bookmark'; + if (!empty($attr['LEVEL'])) { + $objattr['bklevel'] = $attr['LEVEL']; + } else { + $objattr['bklevel'] = 0; + } + $e = Mpdf::OBJECT_IDENTIFIER . "type=bookmark,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + } + /* -- END BOOKMARKS -- */ + if ($this->mpdf->tableLevel) { // *TABLES* + $this->mpdf->_saveCellTextBuffer($e, '', $attr['NAME']); // *TABLES* + } // *TABLES* + else { // *TABLES* + $this->mpdf->_saveTextBuffer($e, '', $attr['NAME']); //an internal link (adds a space for recognition) + } // *TABLES* + } + if (isset($attr['HREF'])) { + $this->mpdf->InlineProperties['A'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('INLINE', 'A', $attr); + if (!empty($properties)) { + $this->mpdf->setCSS($properties, 'INLINE'); + } + $this->mpdf->HREF = $attr['HREF']; // mPDF 5.7.4 URLs + } + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->HREF = ''; + if (isset($this->mpdf->InlineProperties['A'])) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['A']); + } + unset($this->mpdf->InlineProperties['A']); + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Acronym.php b/src/vendor/mpdf/mpdf/src/Tag/Acronym.php new file mode 100644 index 000000000..e33eea53a --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Acronym.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Acronym extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Address.php b/src/vendor/mpdf/mpdf/src/Tag/Address.php new file mode 100644 index 000000000..44b5b3cbb --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Address.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Address extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Annotation.php b/src/vendor/mpdf/mpdf/src/Tag/Annotation.php new file mode 100644 index 000000000..f156fc6fa --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Annotation.php @@ -0,0 +1,101 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Annotation extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + //if (isset($attr['CONTENT']) && !$this->mpdf->writingHTMLheader && !$this->mpdf->writingHTMLfooter) { // Stops annotations in FixedPos + if (isset($attr['CONTENT'])) { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES); + $objattr['type'] = 'annot'; + $objattr['POPUP'] = ''; + } else { + return; + } + if (isset($attr['POS-X'])) { + $objattr['POS-X'] = $attr['POS-X']; + } else { + $objattr['POS-X'] = 0; + } + if (isset($attr['POS-Y'])) { + $objattr['POS-Y'] = $attr['POS-Y']; + } else { + $objattr['POS-Y'] = 0; + } + if (isset($attr['ICON'])) { + $objattr['ICON'] = $attr['ICON']; + } else { + $objattr['ICON'] = 'Note'; + } + if (isset($attr['AUTHOR'])) { + $objattr['AUTHOR'] = $attr['AUTHOR']; + } elseif (isset($attr['TITLE'])) { + $objattr['AUTHOR'] = $attr['TITLE']; + } else { + $objattr['AUTHOR'] = ''; + } + if (isset($attr['FILE'])) { + $objattr['FILE'] = $attr['FILE']; + } else { + $objattr['FILE'] = ''; + } + if (isset($attr['SUBJECT'])) { + $objattr['SUBJECT'] = $attr['SUBJECT']; + } else { + $objattr['SUBJECT'] = ''; + } + if (isset($attr['OPACITY']) && $attr['OPACITY'] > 0 && $attr['OPACITY'] <= 1) { + $objattr['OPACITY'] = $attr['OPACITY']; + } elseif ($this->mpdf->annotMargin) { + $objattr['OPACITY'] = 1; + } else { + $objattr['OPACITY'] = $this->mpdf->annotOpacity; + } + if (isset($attr['COLOR'])) { + $cor = $this->colorConverter->convert($attr['COLOR'], $this->mpdf->PDFAXwarnings); + if ($cor) { + $objattr['COLOR'] = $cor; + } else { + $objattr['COLOR'] = $this->colorConverter->convert('yellow', $this->mpdf->PDFAXwarnings); + } + } else { + $objattr['COLOR'] = $this->colorConverter->convert('yellow', $this->mpdf->PDFAXwarnings); + } + + if (isset($attr['POPUP']) && !empty($attr['POPUP'])) { + $pop = preg_split('/\s+/', trim($attr['POPUP'])); + if (count($pop) > 1) { + $objattr['POPUP'] = $pop; + } else { + $objattr['POPUP'] = true; + } + } + $e = Mpdf::OBJECT_IDENTIFIER . "type=annot,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$e]; + } // *TABLES* + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Article.php b/src/vendor/mpdf/mpdf/src/Tag/Article.php new file mode 100644 index 000000000..180d69d8c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Article.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Article extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Aside.php b/src/vendor/mpdf/mpdf/src/Tag/Aside.php new file mode 100644 index 000000000..fa7e697b3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Aside.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Aside extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/B.php b/src/vendor/mpdf/mpdf/src/Tag/B.php new file mode 100644 index 000000000..15e2eb3e9 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/B.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class B extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/BarCode.php b/src/vendor/mpdf/mpdf/src/Tag/BarCode.php new file mode 100644 index 000000000..40bf5dc41 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/BarCode.php @@ -0,0 +1,271 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class BarCode extends Tag +{ + + /** + * @var \Mpdf\Barcode + */ + protected $barcode; + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->ignorefollowingspaces = false; + if (!empty($attr['CODE'])) { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['quiet_l'] = 0; + $objattr['quiet_r'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['code'] = htmlspecialchars_decode($attr['CODE']); + + if (isset($attr['TYPE'])) { + $objattr['btype'] = strtoupper(trim($attr['TYPE'])); + } else { + $objattr['btype'] = 'EAN13'; + } // default + if (preg_match('/^(EAN13|ISBN|ISSN|EAN8|UPCA|UPCE)P([25])$/', $objattr['btype'], $m)) { + $objattr['btype'] = $m[1]; + $objattr['bsupp'] = $m[2]; + if (preg_match('/^(\S+)\s+(.*)$/', $objattr['code'], $mm)) { + $objattr['code'] = $mm[1]; + $objattr['bsupp_code'] = $mm[2]; + } + } else { + $objattr['bsupp'] = 0; + } + + if (isset($attr['TEXT']) && $attr['TEXT'] == 1) { + $objattr['showtext'] = 1; + } else { + $objattr['showtext'] = 0; + } + if (isset($attr['SIZE']) && $attr['SIZE'] > 0) { + $objattr['bsize'] = $attr['SIZE']; + } else { + $objattr['bsize'] = 1; + } + if (isset($attr['HEIGHT']) && $attr['HEIGHT'] > 0) { + $objattr['bheight'] = $attr['HEIGHT']; + } else { + $objattr['bheight'] = 1; + } + if (isset($attr['PR']) && $attr['PR'] > 0) { + $objattr['pr_ratio'] = $attr['PR']; + } else { + $objattr['pr_ratio'] = ''; + } + if (isset($attr['QUIET_ZONE_LEFT']) && is_numeric($attr['QUIET_ZONE_LEFT'])) { + $objattr['quiet_zone_left'] = $attr['QUIET_ZONE_LEFT']; + } else { + $objattr['quiet_zone_left'] = null; + } + if (isset($attr['QUIET_ZONE_RIGHT']) && is_numeric($attr['QUIET_ZONE_RIGHT'])) { + $objattr['quiet_zone_right'] = $attr['QUIET_ZONE_RIGHT']; + } else { + $objattr['quiet_zone_right'] = null; + } + + $properties = $this->cssManager->MergeCSS('', 'BARCODE', $attr); + if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') { + return; + } + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-LEFT'])) { + $objattr['margin_left'] = $this->sizeConverter->convert( + $properties['MARGIN-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-RIGHT'])) { + $objattr['margin_right'] = $this->sizeConverter->convert( + $properties['MARGIN-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['PADDING-TOP'])) { + $objattr['padding_top'] = $this->sizeConverter->convert( + $properties['PADDING-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-BOTTOM'])) { + $objattr['padding_bottom'] = $this->sizeConverter->convert( + $properties['PADDING-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-LEFT'])) { + $objattr['padding_left'] = $this->sizeConverter->convert( + $properties['PADDING-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-RIGHT'])) { + $objattr['padding_right'] = $this->sizeConverter->convert( + $properties['PADDING-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['BORDER-TOP'])) { + $objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + } + if (isset($properties['BORDER-LEFT'])) { + $objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } + if (isset($properties['BORDER-RIGHT'])) { + $objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } + + if (isset($properties['VERTICAL-ALIGN'])) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + if (isset($properties['COLOR']) && $properties['COLOR'] != '') { + $objattr['color'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } else { + $objattr['color'] = false; + } + if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { + $objattr['bgcolor'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings); + } else { + $objattr['bgcolor'] = false; + } + + $this->barcode = new \Mpdf\Barcode(); + + if (in_array($objattr['btype'], ['EAN13', 'ISBN', 'ISSN', 'UPCA', 'UPCE', 'EAN8'])) { + + $code = preg_replace('/\-/', '', $objattr['code']); + $arrcode = $this->barcode->getBarcodeArray($code, $objattr['btype'], '', $objattr['quiet_l'], $objattr['quiet_r']); + + if ($objattr['bsupp'] == 2 || $objattr['bsupp'] == 5) { // EAN-2 or -5 Supplement + $supparrcode = $this->barcode->getBarcodeArray($objattr['bsupp_code'], 'EAN' . $objattr['bsupp'], '', $objattr['quiet_l'], $objattr['quiet_r']); + $w = ($arrcode['maxw'] + $arrcode['lightmL'] + $arrcode['lightmR'] + + $supparrcode['maxw'] + $supparrcode['sepM']) * $arrcode['nom-X'] * $objattr['bsize']; + } else { + $w = ($arrcode['maxw'] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize']; + } + + $h = $arrcode['nom-H'] * $objattr['bsize'] * $objattr['bheight']; + // Add height for ISBN string + margin from top of bars + if (($objattr['showtext'] && $objattr['btype'] === 'EAN13') || $objattr['btype'] === 'ISBN' || $objattr['btype'] === 'ISSN') { + $tisbnm = 1.5 * $objattr['bsize']; // Top margin between TOP TEXT (isbn - if shown) & bars + $isbn_fontsize = 2.1 * $objattr['bsize']; + $h += $isbn_fontsize + $tisbnm; + } + + } elseif ($objattr['btype'] === 'QR') { // QR-code + $w = $h = $objattr['bsize'] * 25; // Factor of 25mm (default) + $objattr['errorlevel'] = 'L'; + if (isset($attr['ERROR'])) { + $objattr['errorlevel'] = $attr['ERROR']; + } + $objattr['disableborder'] = false; + if (isset($attr['DISABLEBORDER'])) { + $objattr['disableborder'] = (bool) $attr['DISABLEBORDER']; + } + + } elseif (in_array($objattr['btype'], ['IMB', 'RM4SCC', 'KIX', 'POSTNET', 'PLANET'])) { + + $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], '', $objattr['quiet_l'], $objattr['quiet_r']); + + $w = ($arrcode['maxw'] * $arrcode['nom-X'] * $objattr['bsize']) + $arrcode['quietL'] + $arrcode['quietR']; + $h = ($arrcode['nom-H'] * $objattr['bsize']) + (2 * $arrcode['quietTB']); + + } elseif (in_array($objattr['btype'], ['C128A', 'C128B', 'C128C', 'C128RAW', 'EAN128A', 'EAN128B', 'EAN128C', + 'C39', 'C39+', 'C39E', 'C39E+', 'S25', 'S25+', 'I25', 'I25+', 'I25B', + 'I25B+', 'C93', 'MSI', 'MSI+', 'CODABAR', 'CODE11'])) { + + $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], $objattr['pr_ratio'], $objattr['quiet_zone_left'], $objattr['quiet_zone_right']); + $w = ($arrcode['maxw'] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize']; + $h = ((2 * $arrcode['lightTB'] * $arrcode['nom-X']) + $arrcode['nom-H']) * $objattr['bsize'] * $objattr['bheight']; + + } else { + return; + } + + $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w']; + $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w']; + + $objattr['type'] = 'barcode'; + $objattr['height'] = $h + $extraheight; + $objattr['width'] = $w + $extrawidth; + $objattr['barcode_height'] = $h; + $objattr['barcode_width'] = $w; + + /* -- CSS-IMAGE-FLOAT -- */ + if (!$this->mpdf->ColActive && !$this->mpdf->tableLevel && !$this->mpdf->listlvl && !$this->mpdf->kwt) { + if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) === 'RIGHT' || strtoupper($properties['FLOAT']) === 'LEFT')) { + $objattr['float'] = strtoupper(substr($properties['FLOAT'], 0, 1)); + } + } + /* -- END CSS-IMAGE-FLOAT -- */ + + $e = Mpdf::OBJECT_IDENTIFIER . "type=barcode,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Bdi.php b/src/vendor/mpdf/mpdf/src/Tag/Bdi.php new file mode 100644 index 000000000..3de3ec5f7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Bdi.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Bdi extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Bdo.php b/src/vendor/mpdf/mpdf/src/Tag/Bdo.php new file mode 100644 index 000000000..6435d3f17 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Bdo.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Bdo extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Big.php b/src/vendor/mpdf/mpdf/src/Tag/Big.php new file mode 100644 index 000000000..fffd893d1 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Big.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Big extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/BlockQuote.php b/src/vendor/mpdf/mpdf/src/Tag/BlockQuote.php new file mode 100644 index 000000000..44287ca61 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/BlockQuote.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class BlockQuote extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/BlockTag.php b/src/vendor/mpdf/mpdf/src/Tag/BlockTag.php new file mode 100644 index 000000000..7f2ba763e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/BlockTag.php @@ -0,0 +1,1351 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Conversion\DecToAlpha; +use Mpdf\Conversion\DecToRoman; +use Mpdf\Mpdf; +use Mpdf\Utils\Arrays; +use Mpdf\Utils\UtfString; + +abstract class BlockTag extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + + // mPDF 6 Lists + $this->mpdf->lastoptionaltag = ''; + + // mPDF 6 bidi + // Block + // If unicode-bidi set on current clock, any embedding levels, isolates, or overrides are closed (not inherited) + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) { + $blockpost = $this->mpdf->_setBidiCodes('end', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']); + if ($blockpost) { + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($blockpost); + } else { + $this->mpdf->_saveTextBuffer($blockpost); + } + } + } + + + $p = $this->cssManager->PreviewBlockCSS($tag, $attr); + if (isset($p['DISPLAY']) && strtolower($p['DISPLAY']) === 'none') { + $this->mpdf->blklvl++; + $this->mpdf->blk[$this->mpdf->blklvl]['hide'] = true; + $this->mpdf->blk[$this->mpdf->blklvl]['tag'] = $tag; // mPDF 6 + return; + } + if ($tag === 'CAPTION') { + // position is written in AdjstHTML + $divpos = 'T'; + if (isset($attr['POSITION']) && strtolower($attr['POSITION']) === 'bottom') { + $divpos = 'B'; + } + + $cappos = 'T'; + if (isset($attr['ALIGN']) && strtolower($attr['ALIGN']) === 'bottom') { + $cappos = 'B'; + } elseif (isset($p['CAPTION-SIDE']) && strtolower($p['CAPTION-SIDE']) === 'bottom') { + $cappos = 'B'; + } + if (isset($attr['ALIGN'])) { + unset($attr['ALIGN']); + } + if ($cappos != $divpos) { + $this->mpdf->blklvl++; + $this->mpdf->blk[$this->mpdf->blklvl]['hide'] = true; + $this->mpdf->blk[$this->mpdf->blklvl]['tag'] = $tag; // mPDF 6 + return; + } + } + + /* -- FORMS -- */ + if ($tag === 'FORM') { + $this->form->formMethod = 'POST'; + if (isset($attr['METHOD']) && strtolower($attr['METHOD']) === 'get') { + $this->form->formMethod = 'GET'; + } + + $this->form->formAction = ''; + if (isset($attr['ACTION'])) { + $this->form->formAction = $attr['ACTION']; + } + } + /* -- END FORMS -- */ + + + /* -- CSS-POSITION -- */ + if ((isset($p['POSITION']) + && (strtolower($p['POSITION']) === 'fixed' + || strtolower($p['POSITION']) === 'absolute')) + && $this->mpdf->blklvl == 0) { + if ($this->mpdf->inFixedPosBlock) { + throw new \Mpdf\MpdfException('Cannot nest block with position:fixed or position:absolute'); + } + $this->mpdf->inFixedPosBlock = true; + return; + } + /* -- END CSS-POSITION -- */ + // Start Block + $this->mpdf->ignorefollowingspaces = true; + + $lastbottommargin = 0; + if ($this->mpdf->blockjustfinished && !count($this->mpdf->textbuffer) + && $this->mpdf->y != $this->mpdf->tMargin + && $this->mpdf->collapseBlockMargins) { + $lastbottommargin = $this->mpdf->lastblockbottommargin; + } + $this->mpdf->lastblockbottommargin = 0; + $this->mpdf->blockjustfinished = false; + + + $this->mpdf->InlineBDF = []; // mPDF 6 + $this->mpdf->InlineBDFctr = 0; // mPDF 6 + $this->mpdf->InlineProperties = []; + $this->mpdf->divbegin = true; + + $this->mpdf->linebreakjustfinished = false; + + /* -- TABLES -- */ + if ($this->mpdf->tableLevel) { + // If already something on the line + if ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] > 0 && !$this->mpdf->nestedtablejustfinished) { + $this->mpdf->_saveCellTextBuffer("\n"); + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset + } + // Cannot set block properties inside table - use Bold to indicate h1-h6 + if ($tag === 'CENTER' && $this->mpdf->tdbegin) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['a'] = $this->getAlign('center'); + } + + $this->mpdf->InlineProperties['BLOCKINTABLE'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('', $tag, $attr); + if (!empty($properties)) { + $this->mpdf->setCSS($properties, 'INLINE'); + } + + // mPDF 6 Lists + if ($tag === 'UL' || $tag === 'OL') { + $this->mpdf->listlvl++; + if (isset($attr['START'])) { + $this->mpdf->listcounter[$this->mpdf->listlvl] = (int) $attr['START'] - 1; + } else { + $this->mpdf->listcounter[$this->mpdf->listlvl] = 0; + } + $this->mpdf->listitem = []; + if ($tag === 'OL') { + $this->mpdf->listtype[$this->mpdf->listlvl] = 'decimal'; + } elseif ($tag === 'UL') { + if ($this->mpdf->listlvl % 3 == 1) { + $this->mpdf->listtype[$this->mpdf->listlvl] = 'disc'; + } elseif ($this->mpdf->listlvl % 3 == 2) { + $this->mpdf->listtype[$this->mpdf->listlvl] = 'circle'; + } else { + $this->mpdf->listtype[$this->mpdf->listlvl] = 'square'; + } + } + } + + // mPDF 6 Lists - in Tables + if ($tag === 'LI') { + + if ($this->mpdf->listlvl == 0) { //in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...) + $this->mpdf->listlvl++; // first depth level + $this->mpdf->listcounter[$this->mpdf->listlvl] = 0; + } + + $this->mpdf->listcounter[$this->mpdf->listlvl]++; + $this->mpdf->listitem = []; + //if in table - output here as a tabletextbuffer + //position:inside OR position:outside (always output in table as position:inside) + + $decToAlpha = new DecToAlpha(); + $decToRoman = new DecToRoman(); + + switch ($this->mpdf->listtype[$this->mpdf->listlvl]) { + case 'upper-alpha': + case 'upper-latin': + case 'A': + $blt = $decToAlpha->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix; + break; + case 'lower-alpha': + case 'lower-latin': + case 'a': + $blt = $decToAlpha->convert($this->mpdf->listcounter[$this->mpdf->listlvl], false) . $this->mpdf->list_number_suffix; + break; + case 'upper-roman': + case 'I': + $blt = $decToRoman->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix; + break; + case 'lower-roman': + case 'i': + $blt = $decToRoman->convert($this->mpdf->listcounter[$this->mpdf->listlvl]) . $this->mpdf->list_number_suffix; + break; + case 'decimal': + case '1': + $blt = $this->mpdf->listcounter[$this->mpdf->listlvl] . $this->mpdf->list_number_suffix; + break; + default: + $blt = '-'; + if ($this->mpdf->listlvl % 3 == 1 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 8226)) { + $blt = "\xe2\x80\xa2"; + } // • + elseif ($this->mpdf->listlvl % 3 == 2 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 9900)) { + $blt = "\xe2\x9a\xac"; + } // ⚬ + elseif ($this->mpdf->listlvl % 3 == 0 && $this->mpdf->_charDefined($this->mpdf->CurrentFont['cw'], 9642)) { + $blt = "\xe2\x96\xaa"; + } // ▪ + break; + } + + // change to   spaces + if ($this->mpdf->usingCoreFont) { + $ls = str_repeat(chr(160) . chr(160), ($this->mpdf->listlvl - 1) * 2) . $blt . ' '; + } else { + $ls = str_repeat("\xc2\xa0\xc2\xa0", ($this->mpdf->listlvl - 1) * 2) . $blt . ' '; + } + $this->mpdf->_saveCellTextBuffer($ls); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $this->mpdf->GetStringWidth($ls); + } + + return; + } + /* -- END TABLES -- */ + + if ($this->mpdf->lastblocklevelchange == 1) { + $blockstate = 1; + } // Top margins/padding only + elseif ($this->mpdf->lastblocklevelchange < 1) { + $blockstate = 0; + } // NO margins/padding + + $this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate); + $this->mpdf->textbuffer = []; + + $save_blklvl = $this->mpdf->blklvl; + $save_blk = $this->mpdf->blk; + + $this->mpdf->Reset(); + + $pagesel = ''; + /* -- CSS-PAGE -- */ + if (isset($p['PAGE'])) { + $pagesel = $p['PAGE']; + } // mPDF 6 (uses $p - preview of properties so blklvl can be incremented after page-break) + /* -- END CSS-PAGE -- */ + + // If page-box has changed AND/OR PAGE-BREAK-BEFORE + // mPDF 6 (uses $p - preview of properties so blklvl can be incremented after page-break) + if (!$this->mpdf->tableLevel && (($pagesel && (!$this->mpdf->page_box['current'] || $pagesel != $this->mpdf->page_box['current'])) + || (isset($p['PAGE-BREAK-BEFORE']) && $p['PAGE-BREAK-BEFORE']))) { + // mPDF 6 pagebreaktype + $startpage = $this->mpdf->page; + $pagebreaktype = $this->mpdf->defaultPagebreakType; + $this->mpdf->lastblocklevelchange = -1; + if ($this->mpdf->ColActive) { + $pagebreaktype = 'cloneall'; + } + if ($pagesel && (!$this->mpdf->page_box['current'] || $pagesel != $this->mpdf->page_box['current'])) { + $pagebreaktype = 'cloneall'; + } + $this->mpdf->_preForcedPagebreak($pagebreaktype); + + if (isset($p['PAGE-BREAK-BEFORE'])) { + if (strtoupper($p['PAGE-BREAK-BEFORE']) === 'RIGHT') { + $this->mpdf->AddPage( + $this->mpdf->CurOrientation, + 'NEXT-ODD', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 0, + 0, + 0, + 0, + $pagesel + ); + } elseif (strtoupper($p['PAGE-BREAK-BEFORE']) === 'LEFT') { + $this->mpdf->AddPage( + $this->mpdf->CurOrientation, + 'NEXT-EVEN', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 0, + 0, + 0, + 0, + $pagesel + ); + } elseif (strtoupper($p['PAGE-BREAK-BEFORE']) === 'ALWAYS') { + $this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel); + } elseif ($this->mpdf->page_box['current'] != $pagesel) { + $this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel); + } // *CSS-PAGE* + } /* -- CSS-PAGE -- */ + // Must Add new page if changed page properties + elseif (!$this->mpdf->page_box['current'] || $pagesel != $this->mpdf->page_box['current']) { + $this->mpdf->AddPage($this->mpdf->CurOrientation, '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, $pagesel); + } + /* -- END CSS-PAGE -- */ + + // mPDF 6 pagebreaktype + $this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl); + } + + // mPDF 6 pagebreaktype - moved after pagebreak + $this->mpdf->blklvl++; + $currblk = & $this->mpdf->blk[$this->mpdf->blklvl]; + $this->mpdf->initialiseBlock($currblk); + $prevblk = & $this->mpdf->blk[$this->mpdf->blklvl - 1]; + $currblk['tag'] = $tag; + $currblk['attr'] = $attr; + + $properties = $this->cssManager->MergeCSS('BLOCK', $tag, $attr); // mPDF 6 - moved to after page-break-before + // mPDF 6 page-break-inside:avoid + if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) === 'AVOID' + && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together && !isset($attr['PAGEBREAKAVOIDCHECKED'])) { + // avoid re-iterating using PAGEBREAKAVOIDCHECKED; set in CloseTag + $currblk['keep_block_together'] = 1; + $currblk['array_i'] = $ihtml; // mPDF 6 + $this->mpdf->kt_y00 = $this->mpdf->y; + $this->mpdf->kt_p00 = $this->mpdf->page; + $this->mpdf->keep_block_together = 1; + } + if ($lastbottommargin && !empty($properties['MARGIN-TOP']) && empty($properties['FLOAT'])) { + $currblk['lastbottommargin'] = $lastbottommargin; + } + + if (isset($properties['Z-INDEX']) && $this->mpdf->current_layer == 0) { + $v = (int) $properties['Z-INDEX']; + if ($v > 0) { + $currblk['z-index'] = $v; + $this->mpdf->BeginLayer($v); + } + } + + + // mPDF 6 Lists + // List-type set by attribute + if ($tag === 'OL' || $tag === 'UL' || $tag === 'LI') { + if (!empty($attr['TYPE'])) { + $listtype = $attr['TYPE']; + switch ($listtype) { + case 'A': + $listtype = 'upper-latin'; + break; + case 'a': + $listtype = 'lower-latin'; + break; + case 'I': + $listtype = 'upper-roman'; + break; + case 'i': + $listtype = 'lower-roman'; + break; + case '1': + $listtype = 'decimal'; + break; + } + $currblk['list_style_type'] = $listtype; + } + } + + $this->mpdf->setCSS($properties, 'BLOCK', $tag); //name(id/class/style) found in the CSS array! + $currblk['InlineProperties'] = $this->mpdf->saveInlineProperties(); + + if (isset($properties['VISIBILITY'])) { + $v = strtolower($properties['VISIBILITY']); + if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible' && !$this->mpdf->tableLevel) { + $currblk['visibility'] = $v; + $this->mpdf->SetVisibility($v); + } + } + + // mPDF 6 + if (!empty($attr['ALIGN'])) { + $currblk['block-align'] = $this->getAlign($attr['ALIGN']); + } + + + if (isset($properties['HEIGHT'])) { + $currblk['css_set_height'] = $this->sizeConverter->convert( + $properties['HEIGHT'], + $this->mpdf->h - $this->mpdf->tMargin - $this->mpdf->bMargin, + $this->mpdf->FontSize, + false + ); + if (($currblk['css_set_height'] + $this->mpdf->y) > $this->mpdf->PageBreakTrigger + && $this->mpdf->y > $this->mpdf->tMargin + 5 + && $currblk['css_set_height'] < ($this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin))) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + } else { + $currblk['css_set_height'] = false; + } + + + // Added mPDF 3.0 Float DIV + if (isset($prevblk['blockContext'])) { + $currblk['blockContext'] = $prevblk['blockContext']; + } // *CSS-FLOAT* + + if (isset($properties['CLEAR'])) { + $this->mpdf->ClearFloats(strtoupper($properties['CLEAR']), $this->mpdf->blklvl - 1); + } // *CSS-FLOAT* + + $currblk['padding_left'] = is_numeric($currblk['padding_left']) ? $currblk['padding_left'] : 0; + $currblk['padding_right'] = is_numeric($currblk['padding_right']) ? $currblk['padding_right'] : 0; + + $container_w = $prevblk['inner_width']; + $bdr = $currblk['border_right']['w']; + $bdl = $currblk['border_left']['w']; + $pdr = $currblk['padding_right']; + $pdl = $currblk['padding_left']; + + $setwidth = 0; + if (isset($currblk['css_set_width'])) { + $setwidth = $currblk['css_set_width']; + } + + /* -- CSS-FLOAT -- */ + if (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) === 'RIGHT' && !$this->mpdf->ColActive) { + + // Cancel Keep-Block-together + $currblk['keep_block_together'] = false; + $this->mpdf->kt_y00 = 0; + $this->mpdf->keep_block_together = 0; + + $this->mpdf->blockContext++; + $currblk['blockContext'] = $this->mpdf->blockContext; + + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + + // DIV is too narrow for text to fit! + $maxw = $container_w - $l_width - $r_width; + $doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false)); + if (($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw + || ($maxw - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) < (2 * $this->mpdf->GetCharWidth('W', false))) { + // Too narrow to fit - try to move down past L or R float + if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) + && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1); + } elseif ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) + && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1); + } else { + $this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1); + } + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + } + + if ($r_exists) { + $currblk['margin_right'] += $r_width; + } + + $currblk['float'] = 'R'; + $currblk['float_start_y'] = $this->mpdf->y; + + if (isset($currblk['css_set_width'])) { + $currblk['margin_left'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']); + $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']); + } else { + // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width + // and do borders and backgrounds - For now - just set to maximum width left + + if ($l_exists) { + $currblk['margin_left'] += $l_width; + } + $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr); + + $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_right']); + } + + } elseif (isset($properties['FLOAT']) && strtoupper($properties['FLOAT']) === 'LEFT' && !$this->mpdf->ColActive) { + // Cancel Keep-Block-together + $currblk['keep_block_together'] = false; + $this->mpdf->kt_y00 = 0; + $this->mpdf->keep_block_together = 0; + + $this->mpdf->blockContext++; + $currblk['blockContext'] = $this->mpdf->blockContext; + + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + + // DIV is too narrow for text to fit! + $maxw = $container_w - $l_width - $r_width; + $doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false)); + if (($setwidth + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr) > $maxw + || ($maxw - ($currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < (2 * $this->mpdf->GetCharWidth('W', false))) { + // Too narrow to fit - try to move down past L or R float + if ($l_max < $r_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) + && (($container_w - $r_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1); + } elseif ($r_max < $l_max && ($setwidth + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) + && (($container_w - $l_width) - ($currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1); + } else { + $this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1); + } + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + } + + if ($l_exists) { + $currblk['margin_left'] += $l_width; + } + + $currblk['float'] = 'L'; + $currblk['float_start_y'] = $this->mpdf->y; + if ($setwidth) { + $currblk['margin_right'] = $container_w - ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']); + $currblk['float_width'] = ($setwidth + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']); + } else { + // *** If no width set - would need to buffer and keep track of max width, then Right-align if not full width + // and do borders and backgrounds - For now - just set to maximum width left + + if ($r_exists) { + $currblk['margin_right'] += $r_width; + } + $currblk['css_set_width'] = $container_w - ($currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr); + + $currblk['float_width'] = ($currblk['css_set_width'] + $bdl + $pdl + $bdr + $pdr + $currblk['margin_left']); + } + } else { + // Don't allow overlap - if floats present - adjust padding to avoid overlap with Floats + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + $maxw = $container_w - $l_width - $r_width; + + $pdl = is_numeric($pdl) ? $pdl : 0; + $pdr = is_numeric($pdr) ? $pdr : 0; + + $doubleCharWidth = (2 * $this->mpdf->GetCharWidth('W', false)); + if (($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) > $maxw + || ($maxw - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) < $doubleCharWidth) { + // Too narrow to fit - try to move down past L or R float + if ($l_max < $r_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $r_width) + && (($container_w - $r_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('LEFT', $this->mpdf->blklvl - 1); + } elseif ($r_max < $l_max && ($setwidth + $currblk['margin_left'] + $currblk['margin_right'] + $bdl + $pdl + $bdr + $pdr) <= ($container_w - $l_width) + && (($container_w - $l_width) - ($currblk['margin_right'] + $currblk['margin_left'] + $bdl + $pdl + $bdr + $pdr)) > $doubleCharWidth) { + $this->mpdf->ClearFloats('RIGHT', $this->mpdf->blklvl - 1); + } else { + $this->mpdf->ClearFloats('BOTH', $this->mpdf->blklvl - 1); + } + list($l_exists, $r_exists, $l_max, $r_max, $l_width, $r_width) = $this->mpdf->GetFloatDivInfo($this->mpdf->blklvl - 1); + } + if ($r_exists) { + $currblk['padding_right'] = max($r_width - $currblk['margin_right'] - $bdr, $pdr); + } + if ($l_exists) { + $currblk['padding_left'] = max($l_width - $currblk['margin_left'] - $bdl, $pdl); + } + } + /* -- END CSS-FLOAT -- */ + + + /* -- BORDER-RADIUS -- */ + // Automatically increase padding if required for border-radius + if ($this->mpdf->autoPadding && !$this->mpdf->ColActive) { + $currblk['border_radius_TL_H'] = Arrays::get($currblk, 'border_radius_TL_H', 0); + $currblk['border_radius_TL_V'] = Arrays::get($currblk, 'border_radius_TL_V', 0); + $currblk['border_radius_TR_H'] = Arrays::get($currblk, 'border_radius_TR_H', 0); + $currblk['border_radius_TR_V'] = Arrays::get($currblk, 'border_radius_TR_V', 0); + $currblk['border_radius_BL_H'] = Arrays::get($currblk, 'border_radius_BL_H', 0); + $currblk['border_radius_BL_V'] = Arrays::get($currblk, 'border_radius_BL_V', 0); + $currblk['border_radius_BR_H'] = Arrays::get($currblk, 'border_radius_BR_H', 0); + $currblk['border_radius_BR_V'] = Arrays::get($currblk, 'border_radius_BR_V', 0); + + if ($currblk['border_radius_TL_H'] > $currblk['padding_left'] && $currblk['border_radius_TL_V'] > $currblk['padding_top']) { + if ($currblk['border_radius_TL_H'] > $currblk['border_radius_TL_V']) { + $this->mpdf->_borderPadding( + $currblk['border_radius_TL_H'], + $currblk['border_radius_TL_V'], + $currblk['padding_left'], + $currblk['padding_top'] + ); + } else { + $this->mpdf->_borderPadding( + $currblk['border_radius_TL_V'], + $currblk['border_radius_TL_H'], + $currblk['padding_top'], + $currblk['padding_left'] + ); + } + } + if ($currblk['border_radius_TR_H'] > $currblk['padding_right'] && $currblk['border_radius_TR_V'] > $currblk['padding_top']) { + if ($currblk['border_radius_TR_H'] > $currblk['border_radius_TR_V']) { + $this->mpdf->_borderPadding( + $currblk['border_radius_TR_H'], + $currblk['border_radius_TR_V'], + $currblk['padding_right'], + $currblk['padding_top'] + ); + } else { + $this->mpdf->_borderPadding( + $currblk['border_radius_TR_V'], + $currblk['border_radius_TR_H'], + $currblk['padding_top'], + $currblk['padding_right'] + ); + } + } + if ($currblk['border_radius_BL_H'] > $currblk['padding_left'] && $currblk['border_radius_BL_V'] > $currblk['padding_bottom']) { + if ($currblk['border_radius_BL_H'] > $currblk['border_radius_BL_V']) { + $this->mpdf->_borderPadding( + $currblk['border_radius_BL_H'], + $currblk['border_radius_BL_V'], + $currblk['padding_left'], + $currblk['padding_bottom'] + ); + } else { + $this->mpdf->_borderPadding( + $currblk['border_radius_BL_V'], + $currblk['border_radius_BL_H'], + $currblk['padding_bottom'], + $currblk['padding_left'] + ); + } + } + if ($currblk['border_radius_BR_H'] > $currblk['padding_right'] && $currblk['border_radius_BR_V'] > $currblk['padding_bottom']) { + if ($currblk['border_radius_BR_H'] > $currblk['border_radius_BR_V']) { + $this->mpdf->_borderPadding( + $currblk['border_radius_BR_H'], + $currblk['border_radius_BR_V'], + $currblk['padding_right'], + $currblk['padding_bottom'] + ); + } else { + $this->mpdf->_borderPadding( + $currblk['border_radius_BR_V'], + $currblk['border_radius_BR_H'], + $currblk['padding_bottom'], + $currblk['padding_right'] + ); + } + } + } + /* -- END BORDER-RADIUS -- */ + + // Hanging indent - if negative indent: ensure padding is >= indent + if (!isset($currblk['text_indent'])) { + $currblk['text_indent'] = null; + } + if (!isset($currblk['inner_width'])) { + $currblk['inner_width'] = null; + } + $cbti = $this->sizeConverter->convert( + $currblk['text_indent'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + if ($cbti < 0) { + $hangind = -$cbti; + if (isset($currblk['direction']) && $currblk['direction'] === 'rtl') { // *OTL* + $currblk['padding_right'] = max($currblk['padding_right'], $hangind); // *OTL* + } // *OTL* + else { // *OTL* + $currblk['padding_left'] = max($currblk['padding_left'], $hangind); + } // *OTL* + } + + if (isset($currblk['css_set_width'])) { + if (isset($properties['MARGIN-LEFT'], $properties['MARGIN-RIGHT']) + && strtolower($properties['MARGIN-LEFT']) === 'auto' && strtolower($properties['MARGIN-RIGHT']) === 'auto') { + // Try to reduce margins to accomodate - if still too wide, set margin-right/left=0 (reduces width) + $anyextra = $prevblk['inner_width'] - ($currblk['css_set_width'] + $currblk['border_left']['w'] + + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']); + if ($anyextra > 0) { + $currblk['margin_left'] = $currblk['margin_right'] = $anyextra / 2; + } else { + $currblk['margin_left'] = $currblk['margin_right'] = 0; + } + } elseif (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT']) === 'auto') { + // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width) + $currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + + $currblk['padding_right'] + $currblk['margin_right']); + if ($currblk['margin_left'] < 0) { + $currblk['margin_left'] = 0; + } + } elseif (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT']) === 'auto') { + // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width) + $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + + $currblk['border_left']['w'] + $currblk['padding_left'] + + $currblk['border_right']['w'] + $currblk['padding_right'] + $currblk['margin_left']); + if ($currblk['margin_right'] < 0) { + $currblk['margin_right'] = 0; + } + } else { + if ($currblk['direction'] === 'rtl') { // *OTL* + // Try to reduce margin-left to accomodate - if still too wide, set margin-left=0 (reduces width) + $currblk['margin_left'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + + $currblk['padding_right'] + $currblk['margin_right']); // *OTL* + if ($currblk['margin_left'] < 0) { // *OTL* + $currblk['margin_left'] = 0; // *OTL* + } // *OTL* + } // *OTL* + else { // *OTL* + // Try to reduce margin-right to accomodate - if still too wide, set margin-right=0 (reduces width) + $currblk['margin_right'] = $prevblk['inner_width'] - ($currblk['css_set_width'] + + $currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + + $currblk['padding_right'] + $currblk['margin_left']); + if ($currblk['margin_right'] < 0) { + $currblk['margin_right'] = 0; + } + } // *OTL* + } + } + + $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + + $prevblk['border_left']['w'] + $prevblk['padding_left']; + + $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + + $prevblk['border_right']['w'] + $prevblk['padding_right']; + + $currblk['width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']); + + $currblk['inner_width'] = $currblk['width'] + - ($currblk['border_left']['w'] + $currblk['padding_left'] + $currblk['border_right']['w'] + $currblk['padding_right']); + + // Check DIV is not now too narrow to fit text + $mw = 2 * $this->mpdf->GetCharWidth('W', false); + if ($currblk['inner_width'] < $mw) { + $currblk['padding_left'] = 0; + $currblk['padding_right'] = 0; + $currblk['border_left']['w'] = 0.2; + $currblk['border_right']['w'] = 0.2; + $currblk['margin_left'] = 0; + $currblk['margin_right'] = 0; + $currblk['outer_left_margin'] = $prevblk['outer_left_margin'] + $currblk['margin_left'] + + $prevblk['border_left']['w'] + $prevblk['padding_left']; + $currblk['outer_right_margin'] = $prevblk['outer_right_margin'] + $currblk['margin_right'] + + $prevblk['border_right']['w'] + $prevblk['padding_right']; + $currblk['width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin'] + $currblk['outer_left_margin']); + $currblk['inner_width'] = $this->mpdf->pgwidth - ($currblk['outer_right_margin'] + + $currblk['outer_left_margin'] + $currblk['border_left']['w'] + $currblk['padding_left'] + + $currblk['border_right']['w'] + $currblk['padding_right']); + // if ($currblk['inner_width'] < $mw) { throw new \Mpdf\MpdfException("DIV is too narrow for text to fit!"); } + } + + $this->mpdf->x = $this->mpdf->lMargin + $currblk['outer_left_margin']; + + /* -- BACKGROUNDS -- */ + if (!empty($properties['BACKGROUND-IMAGE']) && !$this->mpdf->kwt && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together) { + $ret = $this->mpdf->SetBackground($properties, $currblk['inner_width']); + if ($ret) { + $currblk['background-image'] = $ret; + } + } + /* -- END BACKGROUNDS -- */ + + /* -- TABLES -- */ + if ($this->mpdf->use_kwt && isset($attr['KEEP-WITH-TABLE']) && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together) { + $this->mpdf->kwt = true; + $this->mpdf->kwt_y0 = $this->mpdf->y; + //$this->mpdf->kwt_x0 = $this->mpdf->x; + $this->mpdf->kwt_x0 = $this->mpdf->lMargin; // mPDF 6 + $this->mpdf->kwt_height = 0; + $this->mpdf->kwt_buffer = []; + $this->mpdf->kwt_Links = []; + $this->mpdf->kwt_Annots = []; + $this->mpdf->kwt_moved = false; + $this->mpdf->kwt_saved = false; + $this->mpdf->kwt_Reference = []; + $this->mpdf->kwt_BMoutlines = []; + $this->mpdf->kwt_toc = []; + } else { + /* -- END TABLES -- */ + $this->mpdf->kwt = false; + } // *TABLES* + + // Save x,y coords in case we need to print borders... + $currblk['y0'] = $this->mpdf->y; + $currblk['initial_y0'] = $this->mpdf->y; // mPDF 6 + $currblk['x0'] = $this->mpdf->x; + $currblk['initial_x0'] = $this->mpdf->x; // mPDF 6 + $currblk['initial_startpage'] = $this->mpdf->page; + $currblk['startpage'] = $this->mpdf->page; // mPDF 6 + $this->mpdf->oldy = $this->mpdf->y; + + $this->mpdf->lastblocklevelchange = 1; + + // mPDF 6 Lists + if ($tag === 'OL' || $tag === 'UL') { + $this->mpdf->listlvl++; + if (!empty($attr['START'])) { + $this->mpdf->listcounter[$this->mpdf->listlvl] = (int) $attr['START'] - 1; + } else { + $this->mpdf->listcounter[$this->mpdf->listlvl] = 0; + } + $this->mpdf->listitem = []; + + // List-type + if (empty($currblk['list_style_type'])) { + if ($tag === 'OL') { + $currblk['list_style_type'] = 'decimal'; + } elseif ($tag === 'UL') { + if ($this->mpdf->listlvl % 3 == 1) { + $currblk['list_style_type'] = 'disc'; + } elseif ($this->mpdf->listlvl % 3 == 2) { + $currblk['list_style_type'] = 'circle'; + } else { + $currblk['list_style_type'] = 'square'; + } + } + } + + // List-image + if (empty($currblk['list_style_image'])) { + $currblk['list_style_image'] = 'none'; + } + + // List-position + if (empty($currblk['list_style_position'])) { + $currblk['list_style_position'] = 'outside'; + } + + // Default indentation using padding + if (strtolower($this->mpdf->list_auto_mode) === 'mpdf' && isset($currblk['list_style_position']) + && $currblk['list_style_position'] === 'outside' && isset($currblk['list_style_image']) + && $currblk['list_style_image'] === 'none' && (!isset($currblk['list_style_type']) + || !preg_match('/U\+([a-fA-F0-9]+)/i', $currblk['list_style_type']))) { + $autopadding = $this->mpdf->_getListMarkerWidth($currblk, $ahtml, $ihtml); + if ($this->mpdf->listlvl > 1 || $this->mpdf->list_indent_first_level) { + $autopadding += $this->sizeConverter->convert( + $this->mpdf->list_indent_default, + $currblk['inner_width'], + $this->mpdf->FontSize, + false + ); + } + // autopadding value is applied to left or right according + // to dir of block. Once a CSS value is set for padding it overrides this default value. + if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT'] === 'auto' + && isset($currblk['direction']) && $currblk['direction'] === 'rtl') { + $currblk['padding_right'] = $autopadding; + } elseif (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT'] === 'auto') { + $currblk['padding_left'] = $autopadding; + } + } else { + // Initial default value is set by $this->mpdf->list_indent_default in config.php; this value is applied to left or right according + // to dir of block. Once a CSS value is set for padding it overrides this default value. + if (isset($properties['PADDING-RIGHT']) && $properties['PADDING-RIGHT'] === 'auto' + && isset($currblk['direction']) && $currblk['direction'] === 'rtl') { + $currblk['padding_right'] = $this->sizeConverter->convert( + $this->mpdf->list_indent_default, + $currblk['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($properties['PADDING-LEFT']) && $properties['PADDING-LEFT'] === 'auto') { + $currblk['padding_left'] = $this->sizeConverter->convert( + $this->mpdf->list_indent_default, + $currblk['inner_width'], + $this->mpdf->FontSize, + false + ); + } + } + } + + // mPDF 6 Lists + if ($tag === 'LI') { + if ($this->mpdf->listlvl == 0) { // in case of malformed HTML code. Example:(...)</p><li>Content</li><p>Paragraph1</p>(...) + $this->mpdf->listlvl++; // first depth level + $this->mpdf->listcounter[$this->mpdf->listlvl] = 0; + } + + if (!isset($attr['PAGEBREAKAVOIDCHECKED']) || !$attr['PAGEBREAKAVOIDCHECKED']) { + $this->mpdf->listcounter[$this->mpdf->listlvl]++; + } + + $this->mpdf->listitem = []; + + // Listitem-type + $this->mpdf->_setListMarker($currblk['list_style_type'], $currblk['list_style_image'], $currblk['list_style_position']); + } + + // mPDF 6 Bidirectional formatting for block elements + $bdf = false; + $bdf2 = ''; + $popd = ''; + + // Get current direction + $currdir = 'ltr'; + if (isset($currblk['direction'])) { + $currdir = $currblk['direction']; + } + if (isset($attr['DIR']) && $attr['DIR'] != '') { + $currdir = strtolower($attr['DIR']); + } + if (isset($properties['DIRECTION'])) { + $currdir = strtolower($properties['DIRECTION']); + } + + // mPDF 6 bidi + // cf. http://www.w3.org/TR/css3-writing-modes/#unicode-bidi + if (isset($properties ['UNICODE-BIDI']) + && (strtolower($properties ['UNICODE-BIDI']) === 'bidi-override' || strtolower($properties ['UNICODE-BIDI']) === 'isolate-override')) { + if ($currdir === 'rtl') { + $bdf = 0x202E; + $popd = 'RLOPDF'; + } // U+202E RLO + else { + $bdf = 0x202D; + $popd = 'LROPDF'; + } // U+202D LRO + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'plaintext') { + $bdf = 0x2068; + $popd = 'FSIPDI'; // U+2068 FSI + } + if ($bdf) { + if ($bdf2) { + $bdf2 = UtfString::code2utf($bdf); + } + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer(UtfString::code2utf($bdf) . $bdf2); + } else { + $this->mpdf->_saveTextBuffer(UtfString::code2utf($bdf) . $bdf2); + } + $this->mpdf->biDirectional = true; + $currblk['bidicode'] = $popd; + } + } + + public function close(&$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + + // mPDF 6 bidi + // Block + // If unicode-bidi set, any embedding levels, isolates, or overrides started by this box are closed + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) { + $blockpost = $this->mpdf->_setBidiCodes('end', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']); + if ($blockpost) { + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($blockpost); + } else { + $this->mpdf->_saveTextBuffer($blockpost); + } + } + } + + $this->mpdf->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces + $this->mpdf->blockjustfinished = true; + + $this->mpdf->lastblockbottommargin = $this->mpdf->blk[$this->mpdf->blklvl]['margin_bottom']; + // mPDF 6 Lists + if ($tag === 'UL' || $tag === 'OL') { + if ($this->mpdf->listlvl > 0 && $this->mpdf->tableLevel) { + if (isset($this->mpdf->listtype[$this->mpdf->listlvl])) { + unset($this->mpdf->listtype[$this->mpdf->listlvl]); + } + } + $this->mpdf->listlvl--; + $this->mpdf->listitem = []; + } + if ($tag === 'LI') { + $this->mpdf->listitem = []; + } + + if (preg_match('/^H\d/', $tag) && !$this->mpdf->tableLevel && !$this->mpdf->writingToC) { + if (isset($this->mpdf->h2toc[$tag]) || isset($this->mpdf->h2bookmarks[$tag])) { + $content = ''; + if (count($this->mpdf->textbuffer) == 1) { + $content = $this->mpdf->textbuffer[0][0]; + } else { + for ($i = 0; $i < count($this->mpdf->textbuffer); $i++) { + if (0 !== strpos($this->mpdf->textbuffer[$i][0], Mpdf::OBJECT_IDENTIFIER)) { //inline object + $content .= $this->mpdf->textbuffer[$i][0]; + } + } + } + /* -- TOC -- */ + if (isset($this->mpdf->h2toc[$tag])) { + $objattr = []; + $objattr['type'] = 'toc'; + $objattr['toclevel'] = $this->mpdf->h2toc[$tag]; + $objattr['CONTENT'] = htmlspecialchars($content); + $e = Mpdf::OBJECT_IDENTIFIER . "type=toc,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + array_unshift($this->mpdf->textbuffer, [$e]); + } + /* -- END TOC -- */ + /* -- BOOKMARKS -- */ + if (isset($this->mpdf->h2bookmarks[$tag])) { + $objattr = []; + $objattr['type'] = 'bookmark'; + $objattr['bklevel'] = $this->mpdf->h2bookmarks[$tag]; + $objattr['CONTENT'] = $content; + $e = Mpdf::OBJECT_IDENTIFIER . "type=toc,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + array_unshift($this->mpdf->textbuffer, [$e]); + } + /* -- END BOOKMARKS -- */ + } + } + + /* -- TABLES -- */ + if ($this->mpdf->tableLevel) { + if ($this->mpdf->linebreakjustfinished) { + $this->mpdf->blockjustfinished = false; + } + if (isset($this->mpdf->InlineProperties['BLOCKINTABLE'])) { + if ($this->mpdf->InlineProperties['BLOCKINTABLE']) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['BLOCKINTABLE']); + } + unset($this->mpdf->InlineProperties['BLOCKINTABLE']); + } + if ($tag === 'PRE') { + $this->mpdf->ispre = false; + } + return; + } + /* -- END TABLES -- */ + $this->mpdf->lastoptionaltag = ''; + $this->mpdf->divbegin = false; + + $this->mpdf->linebreakjustfinished = false; + + $this->mpdf->x = $this->mpdf->lMargin + $this->mpdf->blk[$this->mpdf->blklvl]['outer_left_margin']; + + /* -- CSS-FLOAT -- */ + // If float contained in a float, need to extend bottom to allow for it + $currpos = $this->mpdf->page * 1000 + $this->mpdf->y; + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos']) && $this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] > $currpos) { + $old_page = $this->mpdf->page; + $new_page = (int) ($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] / 1000); + if ($old_page != $new_page) { + $s = $this->mpdf->PrintPageBackgrounds(); + // Writes after the marker so not overwritten later by page background etc. + $this->mpdf->pages[$this->mpdf->page] = preg_replace( + '/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', + '\\1' . "\n" . $s . "\n", + $this->mpdf->pages[$this->mpdf->page] + ); + $this->mpdf->pageBackgrounds = []; + $this->mpdf->page = $new_page; + $this->mpdf->ResetMargins(); + $this->mpdf->Reset(); + $this->mpdf->pageoutput[$this->mpdf->page] = []; + } + // mod changes operands to integers before processing + $this->mpdf->y = (round($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; + } + /* -- END CSS-FLOAT -- */ + + + //Print content + $blockstate = 0; + if ($this->mpdf->lastblocklevelchange == 1) { + $blockstate = 3; + } // Top & bottom margins/padding + elseif ($this->mpdf->lastblocklevelchange == -1) { + $blockstate = 2; + } // Bottom margins/padding only + + // called from after e.g. </table> </div> </div> ... Outputs block margin/border and padding + if (count($this->mpdf->textbuffer) && $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1]) { + if (0 !== strpos($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0], Mpdf::OBJECT_IDENTIFIER)) { // not special content + // Right trim last content and adjust OTLdata + if (preg_match('/[ ]+$/', $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0], $m)) { + $strip = strlen($m[0]); + $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0] = substr( + $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0], + 0, + strlen($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0]) - $strip + ); + /* -- OTL -- */ + if (!empty($this->mpdf->CurrentFont['useOTL'])) { + $this->otl->trimOTLdata($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][18], false); // mPDF 6 ZZZ99K + } + /* -- END OTL -- */ + } + } + } + + if (count($this->mpdf->textbuffer) == 0 && $this->mpdf->lastblocklevelchange != 0) { + /*$this->mpdf->newFlowingBlock( + $this->mpdf->blk[$this->mpdf->blklvl]['width'], + $this->mpdf->lineheight, + '', + false, + 2, + true, + (isset($this->mpdf->blk[$this->mpdf->blklvl]['direction']) ? $this->mpdf->blk[$this->mpdf->blklvl]['direction'] : 'ltr') + );*/ + + $this->mpdf->newFlowingBlock( + $this->mpdf->blk[$this->mpdf->blklvl]['width'], + $this->mpdf->lineheight, + '', + false, + $blockstate, + true, + (isset($this->mpdf->blk[$this->mpdf->blklvl]['direction']) ? $this->mpdf->blk[$this->mpdf->blklvl]['direction'] : 'ltr') + ); + + $this->mpdf->finishFlowingBlock(true); // true = END of flowing block + $this->mpdf->PaintDivBB('', $blockstate); + } else { + $this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate); + } + + + $this->mpdf->textbuffer = []; + + if ($this->mpdf->kwt) { + $this->mpdf->kwt_height = $this->mpdf->y - $this->mpdf->kwt_y0; + } + + /* -- CSS-IMAGE-FLOAT -- */ + $this->mpdf->printfloatbuffer(); + /* -- END CSS-IMAGE-FLOAT -- */ + + if ($tag === 'PRE') { + $this->mpdf->ispre = false; + } + + /* -- CSS-FLOAT -- */ + if ($this->mpdf->blk[$this->mpdf->blklvl]['float'] === 'R') { + // If width not set, here would need to adjust and output buffer + $s = $this->mpdf->PrintPageBackgrounds(); + // Writes after the marker so not overwritten later by page background etc. + $this->mpdf->pages[$this->mpdf->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->mpdf->pages[$this->mpdf->page]); + $this->mpdf->pageBackgrounds = []; + $this->mpdf->Reset(); + $this->mpdf->pageoutput[$this->mpdf->page] = []; + + for ($i = ($this->mpdf->blklvl - 1); $i >= 0; $i--) { + if (isset($this->mpdf->blk[$i]['float_endpos'])) { + $this->mpdf->blk[$i]['float_endpos'] = max($this->mpdf->blk[$i]['float_endpos'], $this->mpdf->page * 1000 + $this->mpdf->y); + } else { + $this->mpdf->blk[$i]['float_endpos'] = $this->mpdf->page * 1000 + $this->mpdf->y; + } + } + + $this->mpdf->floatDivs[] = [ + 'side' => 'R', + 'startpage' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'], + 'y0' => $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'], + 'startpos' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'] * 1000 + $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'], + 'endpage' => $this->mpdf->page, + 'y1' => $this->mpdf->y, + 'endpos' => $this->mpdf->page * 1000 + $this->mpdf->y, + 'w' => $this->mpdf->blk[$this->mpdf->blklvl]['float_width'], + 'blklvl' => $this->mpdf->blklvl, + 'blockContext' => $this->mpdf->blk[$this->mpdf->blklvl - 1]['blockContext'] + ]; + + $this->mpdf->y = $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y']; + $this->mpdf->page = $this->mpdf->blk[$this->mpdf->blklvl]['startpage']; + $this->mpdf->ResetMargins(); + $this->mpdf->pageoutput[$this->mpdf->page] = []; + } + if ($this->mpdf->blk[$this->mpdf->blklvl]['float'] === 'L') { + // If width not set, here would need to adjust and output buffer + $s = $this->mpdf->PrintPageBackgrounds(); + // Writes after the marker so not overwritten later by page background etc. + $this->mpdf->pages[$this->mpdf->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->mpdf->pages[$this->mpdf->page]); + $this->mpdf->pageBackgrounds = []; + $this->mpdf->Reset(); + $this->mpdf->pageoutput[$this->mpdf->page] = []; + + for ($i = ($this->mpdf->blklvl - 1); $i >= 0; $i--) { + if (isset($this->mpdf->blk[$i]['float_endpos'])) { + $this->mpdf->blk[$i]['float_endpos'] = max($this->mpdf->blk[$i]['float_endpos'], $this->mpdf->page * 1000 + $this->mpdf->y); + } else { + $this->mpdf->blk[$i]['float_endpos'] = $this->mpdf->page * 1000 + $this->mpdf->y; + } + } + + $this->mpdf->floatDivs[] = [ + 'side' => 'L', + 'startpage' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'], + 'y0' => $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'], + 'startpos' => $this->mpdf->blk[$this->mpdf->blklvl]['startpage'] * 1000 + $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y'], + 'endpage' => $this->mpdf->page, + 'y1' => $this->mpdf->y, + 'endpos' => $this->mpdf->page * 1000 + $this->mpdf->y, + 'w' => $this->mpdf->blk[$this->mpdf->blklvl]['float_width'], + 'blklvl' => $this->mpdf->blklvl, + 'blockContext' => $this->mpdf->blk[$this->mpdf->blklvl - 1]['blockContext'] + ]; + + $this->mpdf->y = $this->mpdf->blk[$this->mpdf->blklvl]['float_start_y']; + $this->mpdf->page = $this->mpdf->blk[$this->mpdf->blklvl]['startpage']; + $this->mpdf->ResetMargins(); + $this->mpdf->pageoutput[$this->mpdf->page] = []; + } + /* -- END CSS-FLOAT -- */ + + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['visibility']) && $this->mpdf->blk[$this->mpdf->blklvl]['visibility'] !== 'visible') { + $this->mpdf->SetVisibility('visible'); + } + + $page_break_after = ''; + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['page_break_after'])) { + $page_break_after = $this->mpdf->blk[$this->mpdf->blklvl]['page_break_after']; + } + + // Reset values + $this->mpdf->Reset(); + + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['z-index']) && $this->mpdf->blk[$this->mpdf->blklvl]['z-index'] > 0) { + $this->mpdf->EndLayer(); + } + + // mPDF 6 page-break-inside:avoid + if ($this->mpdf->blk[$this->mpdf->blklvl]['keep_block_together']) { + $movepage = false; + // If page-break-inside:avoid section has broken to new page but fits on one side - then move: + if (($this->mpdf->page - $this->mpdf->kt_p00) == 1 && $this->mpdf->y < $this->mpdf->kt_y00) { + $movepage = true; + } + if (($this->mpdf->page - $this->mpdf->kt_p00) > 0) { + for ($i = $this->mpdf->page; $i > $this->mpdf->kt_p00; $i--) { + unset($this->mpdf->pages[$i]); + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bb_painted'][$i])) { + unset($this->mpdf->blk[$this->mpdf->blklvl]['bb_painted'][$i]); + } + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['marginCorrected'][$i])) { + unset($this->mpdf->blk[$this->mpdf->blklvl]['marginCorrected'][$i]); + } + if (isset($this->mpdf->pageoutput[$i])) { + unset($this->mpdf->pageoutput[$i]); + } + } + $this->mpdf->page = $this->mpdf->kt_p00; + } + $this->mpdf->keep_block_together = 0; + $this->mpdf->pageoutput[$this->mpdf->page] = []; + + $this->mpdf->y = $this->mpdf->kt_y00; + + $ihtml = $this->mpdf->blk[$this->mpdf->blklvl]['array_i'] - 1; + + $ahtml[$ihtml + 1] .= ' pagebreakavoidchecked="true";'; // avoid re-iterating; read in OpenTag() + + unset($this->mpdf->blk[$this->mpdf->blklvl]); + $this->mpdf->blklvl--; + + for ($blklvl = 1; $blklvl <= $this->mpdf->blklvl; $blklvl++) { + $this->mpdf->blk[$blklvl]['y0'] = $this->mpdf->blk[$blklvl]['initial_y0']; + $this->mpdf->blk[$blklvl]['x0'] = $this->mpdf->blk[$blklvl]['initial_x0']; + $this->mpdf->blk[$blklvl]['startpage'] = $this->mpdf->blk[$blklvl]['initial_startpage']; + } + + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['x0'])) { + $this->mpdf->x = $this->mpdf->blk[$this->mpdf->blklvl]['x0']; + } else { + $this->mpdf->x = $this->mpdf->lMargin; + } + + $this->mpdf->lastblocklevelchange = 0; + $this->mpdf->ResetMargins(); + if ($movepage) { + $this->mpdf->AddPage(); + } + return; + } + + if ($this->mpdf->blklvl > 0) { // ==0 SHOULDN'T HAPPEN - NOT XHTML + if ($this->mpdf->blk[$this->mpdf->blklvl]['tag'] == $tag) { + unset($this->mpdf->blk[$this->mpdf->blklvl]); + $this->mpdf->blklvl--; + } + //else { echo $tag; exit; } // debug - forces error if incorrectly nested html tags + } + + $this->mpdf->lastblocklevelchange = -1; + // Reset Inline-type properties + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties'])) { + $this->mpdf->restoreInlineProperties($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties']); + } + + $this->mpdf->x = $this->mpdf->lMargin + $this->mpdf->blk[$this->mpdf->blklvl]['outer_left_margin']; + + if (!$this->mpdf->tableLevel && $page_break_after) { + $save_blklvl = $this->mpdf->blklvl; + $save_blk = $this->mpdf->blk; + $save_silp = $this->mpdf->saveInlineProperties(); + $save_ilp = $this->mpdf->InlineProperties; + $save_bflp = $this->mpdf->InlineBDF; + $save_bflpc = $this->mpdf->InlineBDFctr; // mPDF 6 + // mPDF 6 pagebreaktype + $startpage = $this->mpdf->page; + $pagebreaktype = $this->mpdf->defaultPagebreakType; + if ($this->mpdf->ColActive) { + $pagebreaktype = 'cloneall'; + } + + // mPDF 6 pagebreaktype + $this->mpdf->_preForcedPagebreak($pagebreaktype); + + if ($page_break_after === 'RIGHT') { + $this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-ODD'); + } elseif ($page_break_after === 'LEFT') { + $this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-EVEN'); + } else { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + + // mPDF 6 pagebreaktype + $this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl); + + $this->mpdf->InlineProperties = $save_ilp; + $this->mpdf->InlineBDF = $save_bflp; + $this->mpdf->InlineBDFctr = $save_bflpc; // mPDF 6 + $this->mpdf->restoreInlineProperties($save_silp); + } + // mPDF 6 bidi + // Block + // If unicode-bidi set, any embedding levels, isolates, or overrides reopened in the continuing block + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) { + $blockpre = $this->mpdf->_setBidiCodes('start', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']); + if ($blockpre) { + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($blockpre); + } else { + $this->mpdf->_saveTextBuffer($blockpre); + } + } + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Bookmark.php b/src/vendor/mpdf/mpdf/src/Tag/Bookmark.php new file mode 100644 index 000000000..47b6907c0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Bookmark.php @@ -0,0 +1,34 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Bookmark extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + if (isset($attr['CONTENT'])) { + $objattr = []; + $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES); + $objattr['type'] = 'bookmark'; + if (!empty($attr['LEVEL'])) { + $objattr['bklevel'] = $attr['LEVEL']; + } else { + $objattr['bklevel'] = 0; + } + $e = Mpdf::OBJECT_IDENTIFIER . "type=bookmark,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$e]; + } // *TABLES* + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Br.php b/src/vendor/mpdf/mpdf/src/Tag/Br.php new file mode 100644 index 000000000..125a18a7b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Br.php @@ -0,0 +1,88 @@ +<?php + +namespace Mpdf\Tag; + +class Br extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + // Added mPDF 3.0 Float DIV - CLEAR + if (isset($attr['STYLE'])) { + $properties = $this->cssManager->readInlineCSS($attr['STYLE']); + if (isset($properties['CLEAR'])) { + $this->mpdf->ClearFloats(strtoupper($properties['CLEAR']), $this->mpdf->blklvl); + } // *CSS-FLOAT* + } + + // mPDF 6 bidi + // Inline + // If unicode-bidi set, any embedding levels, isolates, or overrides started by + // the inline box are closed at the br and reopened on the other side + $blockpre = ''; + $blockpost = ''; + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['bidicode'])) { + $blockpre = $this->mpdf->_setBidiCodes('end', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']); + $blockpost = $this->mpdf->_setBidiCodes('start', $this->mpdf->blk[$this->mpdf->blklvl]['bidicode']); + } + + // Inline + // If unicode-bidi set, any embedding levels, isolates, or overrides started by + // the inline box are closed at the br and reopened on the other side + $inlinepre = ''; + $inlinepost = ''; + $iBDF = []; + if (count($this->mpdf->InlineBDF)) { + foreach ($this->mpdf->InlineBDF as $k => $ib) { + foreach ($ib as $ib2) { + $iBDF[$ib2[1]] = $ib2[0]; + } + } + if (count($iBDF)) { + ksort($iBDF); + for ($i = count($iBDF) - 1; $i >= 0; $i--) { + $inlinepre .= $this->mpdf->_setBidiCodes('end', $iBDF[$i]); + } + for ($i = 0; $i < count($iBDF); $i++) { + $inlinepost .= $this->mpdf->_setBidiCodes('start', $iBDF[$i]); + } + } + } + + /* -- TABLES -- */ + if ($this->mpdf->tableLevel) { + if ($this->mpdf->blockjustfinished) { + $this->mpdf->_saveCellTextBuffer($blockpre . $inlinepre . "\n" . $inlinepost . $blockpost); + } + + $this->mpdf->_saveCellTextBuffer($blockpre . $inlinepre . "\n" . $inlinepost . $blockpost); + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset + } else { + /* -- END TABLES -- */ + if (count($this->mpdf->textbuffer)) { + $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0] = preg_replace( + '/ $/', + '', + $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][0] + ); + if (!empty($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][18])) { + $this->otl->trimOTLdata($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1][18], false); + } // *OTL* + } + $this->mpdf->_saveTextBuffer($blockpre . $inlinepre . "\n" . $inlinepost . $blockpost); + } // *TABLES* + $this->mpdf->ignorefollowingspaces = true; + $this->mpdf->blockjustfinished = false; + + $this->mpdf->linebreakjustfinished = true; + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Caption.php b/src/vendor/mpdf/mpdf/src/Tag/Caption.php new file mode 100644 index 000000000..ffcb99aaf --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Caption.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Caption extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Center.php b/src/vendor/mpdf/mpdf/src/Tag/Center.php new file mode 100644 index 000000000..36fbe774c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Center.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Center extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Cite.php b/src/vendor/mpdf/mpdf/src/Tag/Cite.php new file mode 100644 index 000000000..869cfc4d0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Cite.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Cite extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Code.php b/src/vendor/mpdf/mpdf/src/Tag/Code.php new file mode 100644 index 000000000..47776e7fa --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Code.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Code extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/ColumnBreak.php b/src/vendor/mpdf/mpdf/src/Tag/ColumnBreak.php new file mode 100644 index 000000000..5b2ff05e3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/ColumnBreak.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf\Tag; + +class ColumnBreak extends NewColumn +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Columns.php b/src/vendor/mpdf/mpdf/src/Tag/Columns.php new file mode 100644 index 000000000..c8c883aa0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Columns.php @@ -0,0 +1,67 @@ +<?php + +namespace Mpdf\Tag; + +class Columns extends Tag +{ + /** + * @param string $tag + * @return \Mpdf\Tag\Tag + */ + private function getTagInstance($tag) + { + $className = \Mpdf\Tag::getTagClassName($tag); + if (class_exists($className)) { + return new $className( + $this->mpdf, + $this->cache, + $this->cssManager, + $this->form, + $this->otl, + $this->tableOfContents, + $this->sizeConverter, + $this->colorConverter, + $this->imageProcessor, + $this->languageToFont + ); + } + + return null; + } + + public function open($attr, &$ahtml, &$ihtml) + { + if (isset($attr['COLUMN-COUNT']) && ($attr['COLUMN-COUNT'] || $attr['COLUMN-COUNT'] === '0')) { + // Close any open block tags + for ($b = $this->mpdf->blklvl; $b > 0; $b--) { + if ($t = $this->getTagInstance($this->mpdf->blk[$b]['tag'])) { + $t->close($ahtml, $ihtml); + } + } + if (!empty($this->mpdf->textbuffer)) { //Output previously buffered content + $this->mpdf->printbuffer($this->mpdf->textbuffer); + $this->mpdf->textbuffer = []; + } + + if (!empty($attr['VALIGN'])) { + if ($attr['VALIGN'] === 'J') { + $valign = 'J'; + } else { + $valign = $this->getAlign($attr['VALIGN']); + } + } else { + $valign = ''; + } + if (!empty($attr['COLUMN-GAP'])) { + $this->mpdf->SetColumns($attr['COLUMN-COUNT'], $valign, $attr['COLUMN-GAP']); + } else { + $this->mpdf->SetColumns($attr['COLUMN-COUNT'], $valign); + } + } + $this->mpdf->ignorefollowingspaces = true; + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Dd.php b/src/vendor/mpdf/mpdf/src/Tag/Dd.php new file mode 100644 index 000000000..ce0ccfb77 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Dd.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Dd extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Del.php b/src/vendor/mpdf/mpdf/src/Tag/Del.php new file mode 100644 index 000000000..8af9cd0a4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Del.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Del extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Details.php b/src/vendor/mpdf/mpdf/src/Tag/Details.php new file mode 100644 index 000000000..bd81da06a --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Details.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Details extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Div.php b/src/vendor/mpdf/mpdf/src/Tag/Div.php new file mode 100644 index 000000000..30fb2b709 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Div.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Div extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Dl.php b/src/vendor/mpdf/mpdf/src/Tag/Dl.php new file mode 100644 index 000000000..80bafc215 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Dl.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Dl extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/DotTab.php b/src/vendor/mpdf/mpdf/src/Tag/DotTab.php new file mode 100644 index 000000000..0537a909d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/DotTab.php @@ -0,0 +1,70 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class DotTab extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $objattr = []; + $objattr['type'] = 'dottab'; + $dots = str_repeat('.', 3) . ' '; // minimum number of dots + $objattr['width'] = $this->mpdf->GetStringWidth($dots); + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['height'] = 0; + $objattr['colorarray'] = $this->mpdf->colorarray; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['vertical_align'] = 'BS'; // mPDF 6 DOTTAB + + $properties = $this->cssManager->MergeCSS('INLINE', 'DOTTAB', $attr); + if (isset($properties['OUTDENT'])) { + $objattr['outdent'] = $this->sizeConverter->convert( + $properties['OUTDENT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['OUTDENT'])) { + $objattr['outdent'] = $this->sizeConverter->convert( + $attr['OUTDENT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } else { + $objattr['outdent'] = 0; + } + + $objattr['fontfamily'] = $this->mpdf->FontFamily; + $objattr['fontsize'] = $this->mpdf->FontSizePt; + + $e = Mpdf::OBJECT_IDENTIFIER . "type=dottab,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset + $this->mpdf->_saveCellTextBuffer($e); + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e); + } // *TABLES* + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Dt.php b/src/vendor/mpdf/mpdf/src/Tag/Dt.php new file mode 100644 index 000000000..22492fb35 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Dt.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Dt extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Em.php b/src/vendor/mpdf/mpdf/src/Tag/Em.php new file mode 100644 index 000000000..a353bd22e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Em.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Em extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/FieldSet.php b/src/vendor/mpdf/mpdf/src/Tag/FieldSet.php new file mode 100644 index 000000000..33356f168 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/FieldSet.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class FieldSet extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/FigCaption.php b/src/vendor/mpdf/mpdf/src/Tag/FigCaption.php new file mode 100644 index 000000000..1e738a546 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/FigCaption.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class FigCaption extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Figure.php b/src/vendor/mpdf/mpdf/src/Tag/Figure.php new file mode 100644 index 000000000..1074a6370 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Figure.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Figure extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Font.php b/src/vendor/mpdf/mpdf/src/Tag/Font.php new file mode 100644 index 000000000..e29041466 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Font.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Font extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Footer.php b/src/vendor/mpdf/mpdf/src/Tag/Footer.php new file mode 100644 index 000000000..46abbc439 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Footer.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Footer extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Form.php b/src/vendor/mpdf/mpdf/src/Tag/Form.php new file mode 100644 index 000000000..588000efd --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Form.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Form extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/FormFeed.php b/src/vendor/mpdf/mpdf/src/Tag/FormFeed.php new file mode 100644 index 000000000..6b2f46b17 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/FormFeed.php @@ -0,0 +1,293 @@ +<?php + +namespace Mpdf\Tag; + +class FormFeed extends Tag +{ + public $toc_id; + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + if (isset($attr['SHEET-SIZE'])) { + // Convert to same types as accepted in initial mPDF() A4, A4-L, or array(w,h) + $prop = preg_split('/\s+/', trim($attr['SHEET-SIZE'])); + if (count($prop) == 2) { + $newformat = [$this->sizeConverter->convert($prop[0]), $this->sizeConverter->convert($prop[1])]; + } else { + $newformat = $attr['SHEET-SIZE']; + } + } else { + $newformat = ''; + } + + $save_blklvl = $this->mpdf->blklvl; + $save_blk = $this->mpdf->blk; + $save_silp = $this->mpdf->saveInlineProperties(); + $save_ilp = $this->mpdf->InlineProperties; + $save_bflp = $this->mpdf->InlineBDF; + $save_bflpc = $this->mpdf->InlineBDFctr; // mPDF 6 + + $mgr = $mgl = $mgt = $mgb = $mgh = $mgf = ''; + if (isset($attr['MARGIN-RIGHT'])) { + $mgr = $this->sizeConverter->convert($attr['MARGIN-RIGHT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['MARGIN-LEFT'])) { + $mgl = $this->sizeConverter->convert($attr['MARGIN-LEFT'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['MARGIN-TOP'])) { + $mgt = $this->sizeConverter->convert($attr['MARGIN-TOP'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['MARGIN-BOTTOM'])) { + $mgb = $this->sizeConverter->convert($attr['MARGIN-BOTTOM'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['MARGIN-HEADER'])) { + $mgh = $this->sizeConverter->convert($attr['MARGIN-HEADER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + if (isset($attr['MARGIN-FOOTER'])) { + $mgf = $this->sizeConverter->convert($attr['MARGIN-FOOTER'], $this->mpdf->w, $this->mpdf->FontSize, false); + } + $ohname = $ehname = $ofname = $efname = ''; + if (isset($attr['ODD-HEADER-NAME'])) { + $ohname = $attr['ODD-HEADER-NAME']; + } + if (isset($attr['EVEN-HEADER-NAME'])) { + $ehname = $attr['EVEN-HEADER-NAME']; + } + if (isset($attr['ODD-FOOTER-NAME'])) { + $ofname = $attr['ODD-FOOTER-NAME']; + } + if (isset($attr['EVEN-FOOTER-NAME'])) { + $efname = $attr['EVEN-FOOTER-NAME']; + } + $ohvalue = $ehvalue = $ofvalue = $efvalue = 0; + if (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE'] == '1' || strtoupper($attr['ODD-HEADER-VALUE']) === 'ON')) { + $ohvalue = 1; + } elseif (isset($attr['ODD-HEADER-VALUE']) && ($attr['ODD-HEADER-VALUE'] == '-1' || strtoupper($attr['ODD-HEADER-VALUE']) === 'OFF')) { + $ohvalue = -1; + } + if (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE'] == '1' || strtoupper($attr['EVEN-HEADER-VALUE']) === 'ON')) { + $ehvalue = 1; + } elseif (isset($attr['EVEN-HEADER-VALUE']) && ($attr['EVEN-HEADER-VALUE'] == '-1' || strtoupper($attr['EVEN-HEADER-VALUE']) === 'OFF')) { + $ehvalue = -1; + } + if (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE'] == '1' || strtoupper($attr['ODD-FOOTER-VALUE']) === 'ON')) { + $ofvalue = 1; + } elseif (isset($attr['ODD-FOOTER-VALUE']) && ($attr['ODD-FOOTER-VALUE'] == '-1' || strtoupper($attr['ODD-FOOTER-VALUE']) === 'OFF')) { + $ofvalue = -1; + } + if (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE'] == '1' || strtoupper($attr['EVEN-FOOTER-VALUE']) === 'ON')) { + $efvalue = 1; + } elseif (isset($attr['EVEN-FOOTER-VALUE']) && ($attr['EVEN-FOOTER-VALUE'] == '-1' || strtoupper($attr['EVEN-FOOTER-VALUE']) === 'OFF')) { + $efvalue = -1; + } + + if (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION']) === 'L' || strtoupper($attr['ORIENTATION']) === 'LANDSCAPE')) { + $orient = 'L'; + } elseif (isset($attr['ORIENTATION']) && (strtoupper($attr['ORIENTATION']) === 'P' || strtoupper($attr['ORIENTATION']) === 'PORTRAIT')) { + $orient = 'P'; + } else { + $orient = $this->mpdf->CurOrientation; + } + + $pagesel = ''; + if (!empty($attr['PAGE-SELECTOR'])) { + $pagesel = $attr['PAGE-SELECTOR']; + } + + // mPDF 6 pagebreaktype + $pagebreaktype = $this->mpdf->defaultPagebreakType; + if ($tag === 'FORMFEED') { + $pagebreaktype = 'slice'; + } // can be overridden by PAGE-BREAK-TYPE + $startpage = $this->mpdf->page; + if (isset($attr['PAGE-BREAK-TYPE'])) { + if (strtolower($attr['PAGE-BREAK-TYPE']) === 'cloneall' + || strtolower($attr['PAGE-BREAK-TYPE']) === 'clonebycss' + || strtolower($attr['PAGE-BREAK-TYPE']) === 'slice') { + $pagebreaktype = strtolower($attr['PAGE-BREAK-TYPE']); + } + } + if ($tag === 'TOCPAGEBREAK') { + $pagebreaktype = 'cloneall'; + } elseif ($this->mpdf->ColActive) { + $pagebreaktype = 'cloneall'; + } // Any change in headers/footers (may need to _getHtmlHeight), or page size/orientation, @page selector, or margins - force cloneall + elseif ($mgr !== '' || $mgl !== '' || $mgt !== '' || $mgb !== '' || $mgh !== '' || $mgf !== '' || + $ohname !== '' || $ehname !== '' || $ofname !== '' || $efname !== '' || + $ohvalue || $ehvalue || $ofvalue || $efvalue || + $orient != $this->mpdf->CurOrientation || $newformat || $pagesel) { + $pagebreaktype = 'cloneall'; + } + + // mPDF 6 pagebreaktype + $this->mpdf->_preForcedPagebreak($pagebreaktype); + + $this->mpdf->ignorefollowingspaces = true; + + + $resetpagenum = ''; + $pagenumstyle = ''; + $suppress = ''; + if (isset($attr['RESETPAGENUM'])) { + $resetpagenum = $attr['RESETPAGENUM']; + } + if (isset($attr['PAGENUMSTYLE'])) { + $pagenumstyle = $attr['PAGENUMSTYLE']; + } + if (isset($attr['SUPPRESS'])) { + $suppress = $attr['SUPPRESS']; + } + + $type = ''; + if ($tag === 'TOCPAGEBREAK') { + $type = 'NEXT-ODD'; + } elseif (isset($attr['TYPE'])) { + $type = strtoupper($attr['TYPE']); + } + + if ($type === 'E' || $type === 'EVEN') { + $this->mpdf->AddPage( + $orient, + 'E', + $resetpagenum, + $pagenumstyle, + $suppress, + $mgl, + $mgr, + $mgt, + $mgb, + $mgh, + $mgf, + $ohname, + $ehname, + $ofname, + $efname, + $ohvalue, + $ehvalue, + $ofvalue, + $efvalue, + $pagesel, + $newformat + ); + } elseif ($type === 'O' || $type === 'ODD') { + $this->mpdf->AddPage( + $orient, + 'O', + $resetpagenum, + $pagenumstyle, + $suppress, + $mgl, + $mgr, + $mgt, + $mgb, + $mgh, + $mgf, + $ohname, + $ehname, + $ofname, + $efname, + $ohvalue, + $ehvalue, + $ofvalue, + $efvalue, + $pagesel, + $newformat + ); + } elseif ($type === 'NEXT-ODD') { + $this->mpdf->AddPage( + $orient, + 'NEXT-ODD', + $resetpagenum, + $pagenumstyle, + $suppress, + $mgl, + $mgr, + $mgt, + $mgb, + $mgh, + $mgf, + $ohname, + $ehname, + $ofname, + $efname, + $ohvalue, + $ehvalue, + $ofvalue, + $efvalue, + $pagesel, + $newformat + ); + } elseif ($type === 'NEXT-EVEN') { + $this->mpdf->AddPage( + $orient, + 'NEXT-EVEN', + $resetpagenum, + $pagenumstyle, + $suppress, + $mgl, + $mgr, + $mgt, + $mgb, + $mgh, + $mgf, + $ohname, + $ehname, + $ofname, + $efname, + $ohvalue, + $ehvalue, + $ofvalue, + $efvalue, + $pagesel, + $newformat + ); + } else { + $this->mpdf->AddPage( + $orient, + '', + $resetpagenum, + $pagenumstyle, + $suppress, + $mgl, + $mgr, + $mgt, + $mgb, + $mgh, + $mgf, + $ohname, + $ehname, + $ofname, + $efname, + $ohvalue, + $ehvalue, + $ofvalue, + $efvalue, + $pagesel, + $newformat + ); + } + + /* -- TOC -- */ + if ($tag === 'TOCPAGEBREAK') { + if ($this->toc_id) { + $this->tableOfContents->m_TOC[$this->toc_id]['TOCmark'] = $this->mpdf->page; + } else { + $this->tableOfContents->TOCmark = $this->mpdf->page; + } + } + /* -- END TOC -- */ + + // mPDF 6 pagebreaktype + $this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl); + + $this->mpdf->InlineProperties = $save_ilp; + $this->mpdf->InlineBDF = $save_bflp; + $this->mpdf->InlineBDFctr = $save_bflpc; // mPDF 6 + $this->mpdf->restoreInlineProperties($save_silp); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H1.php b/src/vendor/mpdf/mpdf/src/Tag/H1.php new file mode 100644 index 000000000..5174afbb8 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H1.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H1 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H2.php b/src/vendor/mpdf/mpdf/src/Tag/H2.php new file mode 100644 index 000000000..199bb55ff --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H2.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H2 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H3.php b/src/vendor/mpdf/mpdf/src/Tag/H3.php new file mode 100644 index 000000000..b9db924cd --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H3.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H3 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H4.php b/src/vendor/mpdf/mpdf/src/Tag/H4.php new file mode 100644 index 000000000..3083ba100 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H4.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H4 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H5.php b/src/vendor/mpdf/mpdf/src/Tag/H5.php new file mode 100644 index 000000000..50b78d746 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H5.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H5 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/H6.php b/src/vendor/mpdf/mpdf/src/Tag/H6.php new file mode 100644 index 000000000..f33dacf34 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/H6.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class H6 extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/HGroup.php b/src/vendor/mpdf/mpdf/src/Tag/HGroup.php new file mode 100644 index 000000000..e519b936e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/HGroup.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class HGroup extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Header.php b/src/vendor/mpdf/mpdf/src/Tag/Header.php new file mode 100644 index 000000000..f94855915 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Header.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Header extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Hr.php b/src/vendor/mpdf/mpdf/src/Tag/Hr.php new file mode 100644 index 000000000..8d023f2ab --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Hr.php @@ -0,0 +1,127 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; +use Mpdf\Utils\NumericString; + +class Hr extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + + // Added mPDF 3.0 Float DIV - CLEAR + if (isset($attr['STYLE'])) { + $properties = $this->cssManager->readInlineCSS($attr['STYLE']); + if (isset($properties['CLEAR'])) { + $this->mpdf->ClearFloats(strtoupper($properties['CLEAR']), $this->mpdf->blklvl); + } // *CSS-FLOAT* + } + + $this->mpdf->ignorefollowingspaces = true; + + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $properties = $this->cssManager->MergeCSS('', 'HR', $attr); + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['WIDTH'])) { + $objattr['width'] = $this->sizeConverter->convert($properties['WIDTH'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + } elseif (isset($attr['WIDTH']) && $attr['WIDTH'] != '') { + $objattr['width'] = $this->sizeConverter->convert($attr['WIDTH'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + } + if (isset($properties['TEXT-ALIGN'])) { + $objattr['align'] = $this->getAlign($properties['TEXT-ALIGN']); + } elseif (isset($attr['ALIGN']) && $attr['ALIGN'] != '') { + $objattr['align'] = $this->getAlign($attr['ALIGN']); + } + + if (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT']) === 'auto') { + $objattr['align'] = 'R'; + } + if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT']) === 'auto') { + $objattr['align'] = 'L'; + if (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT']) === 'auto' + && isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT']) === 'auto') { + $objattr['align'] = 'C'; + } + } + if (isset($properties['COLOR'])) { + $objattr['color'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } elseif (isset($attr['COLOR']) && $attr['COLOR'] != '') { + $objattr['color'] = $this->colorConverter->convert($attr['COLOR'], $this->mpdf->PDFAXwarnings); + } + if (isset($properties['HEIGHT'])) { + $objattr['linewidth'] = $this->sizeConverter->convert( + $properties['HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + + /* -- TABLES -- */ + if ($this->mpdf->tableLevel) { + $objattr['W-PERCENT'] = 100; + if (isset($properties['WIDTH']) && NumericString::containsPercentChar($properties['WIDTH'])) { + $properties['WIDTH'] = NumericString::removePercentChar($properties['WIDTH']); // make "90%" become simply "90" + $objattr['W-PERCENT'] = $properties['WIDTH']; + } + if (isset($attr['WIDTH']) && NumericString::containsPercentChar($attr['WIDTH'])) { + $attr['WIDTH'] = NumericString::removePercentChar($attr['WIDTH']); // make "90%" become simply "90" + $objattr['W-PERCENT'] = $attr['WIDTH']; + } + } + /* -- END TABLES -- */ + + $objattr['type'] = 'hr'; + $objattr['height'] = $objattr['linewidth'] + $objattr['margin_top'] + $objattr['margin_bottom']; + $e = Mpdf::OBJECT_IDENTIFIER . "type=image,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + if ($this->mpdf->cell) { + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + } + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/I.php b/src/vendor/mpdf/mpdf/src/Tag/I.php new file mode 100644 index 000000000..8c03c2dad --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/I.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class I extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Img.php b/src/vendor/mpdf/mpdf/src/Tag/Img.php new file mode 100644 index 000000000..efd3ed94b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Img.php @@ -0,0 +1,458 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Img extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->ignorefollowingspaces = false; + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + if (isset($attr['SRC'])) { + $srcpath = $attr['SRC']; + $orig_srcpath = (isset($attr['ORIG_SRC']) ? $attr['ORIG_SRC'] : ''); + $properties = $this->cssManager->MergeCSS('', 'IMG', $attr); + if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') { + return; + } + if (isset($properties['Z-INDEX']) && $this->mpdf->current_layer == 0) { + $v = (int) $properties['Z-INDEX']; + if ($v > 0) { + $objattr['z-index'] = $v; + } + } + + $objattr['visibility'] = 'visible'; + if (isset($properties['VISIBILITY'])) { + $v = strtolower($properties['VISIBILITY']); + if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible') { + $objattr['visibility'] = $v; + } + } + + // VSPACE and HSPACE converted to margins in MergeCSS + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-LEFT'])) { + $objattr['margin_left'] = $this->sizeConverter->convert( + $properties['MARGIN-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-RIGHT'])) { + $objattr['margin_right'] = $this->sizeConverter->convert( + $properties['MARGIN-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['PADDING-TOP'])) { + $objattr['padding_top'] = $this->sizeConverter->convert( + $properties['PADDING-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-BOTTOM'])) { + $objattr['padding_bottom'] = $this->sizeConverter->convert( + $properties['PADDING-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-LEFT'])) { + $objattr['padding_left'] = $this->sizeConverter->convert( + $properties['PADDING-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-RIGHT'])) { + $objattr['padding_right'] = $this->sizeConverter->convert( + $properties['PADDING-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['BORDER-TOP'])) { + $objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + } + if (isset($properties['BORDER-LEFT'])) { + $objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } + if (isset($properties['BORDER-RIGHT'])) { + $objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } + + if (isset($properties['VERTICAL-ALIGN'])) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + $w = 0; + $h = 0; + if (isset($properties['WIDTH'])) { + $w = $this->sizeConverter->convert( + $properties['WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['WIDTH'])) { + $w = $this->sizeConverter->convert( + $attr['WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['HEIGHT'])) { + $h = $this->sizeConverter->convert( + $properties['HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['HEIGHT'])) { + $h = $this->sizeConverter->convert( + $attr['HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + $maxw = $maxh = $minw = $minh = false; + if (isset($properties['MAX-WIDTH'])) { + $maxw = $this->sizeConverter->convert( + $properties['MAX-WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['MAX-WIDTH'])) { + $maxw = $this->sizeConverter->convert( + $attr['MAX-WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MAX-HEIGHT'])) { + $maxh = $this->sizeConverter->convert( + $properties['MAX-HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['MAX-HEIGHT'])) { + $maxh = $this->sizeConverter->convert( + $attr['MAX-HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MIN-WIDTH'])) { + $minw = $this->sizeConverter->convert( + $properties['MIN-WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['MIN-WIDTH'])) { + $minw = $this->sizeConverter->convert( + $attr['MIN-WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MIN-HEIGHT'])) { + $minh = $this->sizeConverter->convert( + $properties['MIN-HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['MIN-HEIGHT'])) { + $minh = $this->sizeConverter->convert( + $attr['MIN-HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { + $objattr['opacity'] = $properties['OPACITY']; + } + if ($this->mpdf->HREF) { + if (strpos($this->mpdf->HREF, '.') === false && strpos($this->mpdf->HREF, '@') !== 0) { + $href = $this->mpdf->HREF; + while (array_key_exists($href, $this->mpdf->internallink)) { + $href = '#' . $href; + } + $this->mpdf->internallink[$href] = $this->mpdf->AddLink(); + $objattr['link'] = $this->mpdf->internallink[$href]; + } else { + $objattr['link'] = $this->mpdf->HREF; + } + } + $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w']; + + $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w']; + + // mPDF 5.7.3 TRANSFORMS + if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { + $objattr['bgcolor'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings); + } + + /* -- BACKGROUNDS -- */ + if (isset($properties['GRADIENT-MASK']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $properties['GRADIENT-MASK'])) { + $objattr['GRADIENT-MASK'] = $properties['GRADIENT-MASK']; + } + /* -- END BACKGROUNDS -- */ + + // mPDF 6 + $interpolation = false; + if (!empty($properties['IMAGE-RENDERING'])) { + $interpolation = false; + if (strtolower($properties['IMAGE-RENDERING']) === 'crisp-edges') { + $interpolation = false; + } elseif (strtolower($properties['IMAGE-RENDERING']) === 'optimizequality') { + $interpolation = true; + } elseif (strtolower($properties['IMAGE-RENDERING']) === 'smooth') { + $interpolation = true; + } elseif (strtolower($properties['IMAGE-RENDERING']) === 'auto') { + $interpolation = $this->mpdf->interpolateImages; + } + $info['interpolation'] = $interpolation; + } + + // Image file + $info = $this->imageProcessor->getImage($srcpath, true, true, $orig_srcpath, $interpolation); // mPDF 6 + if (!$info) { + $info = $this->imageProcessor->getImage($this->mpdf->noImageFile); + if ($info) { + $srcpath = $this->mpdf->noImageFile; + $w = ($info['w'] * (25.4 / $this->mpdf->img_dpi)); + $h = ($info['h'] * (25.4 / $this->mpdf->img_dpi)); + } + } + if (!$info) { + return; + } + + $image_orientation = 0; + if (isset($attr['ROTATE'])) { + $image_orientation = $attr['ROTATE']; + } elseif (isset($properties['IMAGE-ORIENTATION'])) { + $image_orientation = $properties['IMAGE-ORIENTATION']; + } + if ($image_orientation) { + if ($image_orientation == 90 || $image_orientation == -90 || $image_orientation == 270) { + $tmpw = $info['w']; + $info['w'] = $info['h']; + $info['h'] = $tmpw; + } + $objattr['ROTATE'] = $image_orientation; + } + + $objattr['file'] = $srcpath; + //Default width and height calculation if needed + if ($w == 0 && $h == 0) { + /* -- IMAGES-WMF -- */ + if ($info['type'] === 'wmf') { + // WMF units are twips (1/20pt) + // divide by 20 to get points + // divide by k to get user units + $w = abs($info['w']) / (20 * Mpdf::SCALE); + $h = abs($info['h']) / (20 * Mpdf::SCALE); + } else { /* -- END IMAGES-WMF -- */ + if ($info['type'] === 'svg') { + // SVG units are pixels + $w = abs($info['w']) / Mpdf::SCALE; + $h = abs($info['h']) / Mpdf::SCALE; + } else { + //Put image at default image dpi + $w = ($info['w'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi); + $h = ($info['h'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi); + } + } + if (isset($properties['IMAGE-RESOLUTION'])) { + if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi'] > 0) { + $w *= $this->mpdf->img_dpi / $info['set-dpi']; + $h *= $this->mpdf->img_dpi / $info['set-dpi']; + } elseif (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) { + $dpi = $m[1]; + if ($dpi > 0) { + $w *= $this->mpdf->img_dpi / $dpi; + $h *= $this->mpdf->img_dpi / $dpi; + } + } + } + } + // IF WIDTH OR HEIGHT SPECIFIED + if ($w == 0) { + $w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF; + } + + if ($h == 0) { + $h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF; + } + + if ($minw && $w < $minw) { + $w = $minw; + $h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF; + } + if ($maxw && $w > $maxw) { + $w = $maxw; + $h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF; + } + if ($minh && $h < $minh) { + $h = $minh; + $w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF; + } + if ($maxh && $h > $maxh) { + $h = $maxh; + $w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF; + } + + // Resize to maximum dimensions of page + $maxWidth = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; + $maxHeight = $this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin + 1); + if ($this->mpdf->fullImageHeight) { + $maxHeight = $this->mpdf->fullImageHeight; + } + if (($w + $extrawidth) > ($maxWidth + 0.0001)) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth + $w = $maxWidth - $extrawidth; + $h = abs($w * $info['h'] / $info['w']); + } + + if ($h + $extraheight > $maxHeight) { + $h = $maxHeight - $extraheight; + $w = abs($h * $info['w'] / $info['h']); + } + $objattr['type'] = 'image'; + $objattr['itype'] = $info['type']; + + $objattr['orig_h'] = $info['h']; + $objattr['orig_w'] = $info['w']; + /* -- IMAGES-WMF -- */ + if ($info['type'] === 'wmf') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + } else { /* -- END IMAGES-WMF -- */ + if ($info['type'] === 'svg') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + } + } + $objattr['height'] = $h + $extraheight; + $objattr['width'] = $w + $extrawidth; + $objattr['image_height'] = $h; + $objattr['image_width'] = $w; + /* -- CSS-IMAGE-FLOAT -- */ + if (!$this->mpdf->ColActive && !$this->mpdf->tableLevel && !$this->mpdf->listlvl && !$this->mpdf->kwt) { + if (isset($properties['FLOAT']) && (strtoupper($properties['FLOAT']) === 'RIGHT' || strtoupper($properties['FLOAT']) === 'LEFT')) { + $objattr['float'] = strtoupper(substr($properties['FLOAT'], 0, 1)); + } + } + /* -- END CSS-IMAGE-FLOAT -- */ + // mPDF 5.7.3 TRANSFORMS + if (isset($properties['TRANSFORM']) && !$this->mpdf->ColActive && !$this->mpdf->kwt) { + $objattr['transform'] = $properties['TRANSFORM']; + } + + $e = Mpdf::OBJECT_IDENTIFIER . "type=image,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + /* -- ANNOTATIONS -- */ + if ($this->mpdf->title2annots && isset($attr['TITLE'])) { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['CONTENT'] = $attr['TITLE']; + $objattr['type'] = 'annot'; + $objattr['POS-X'] = 0; + $objattr['POS-Y'] = 0; + $objattr['ICON'] = 'Comment'; + $objattr['AUTHOR'] = ''; + $objattr['SUBJECT'] = ''; + $objattr['OPACITY'] = $this->mpdf->annotOpacity; + $objattr['COLOR'] = $this->colorConverter->convert('yellow', $this->mpdf->PDFAXwarnings); + $e = Mpdf::OBJECT_IDENTIFIER . "type=annot,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { // *TABLES* + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; // *TABLES* + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$e]; + } // *TABLES* + } + /* -- END ANNOTATIONS -- */ + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/IndexEntry.php b/src/vendor/mpdf/mpdf/src/Tag/IndexEntry.php new file mode 100644 index 000000000..01008594c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/IndexEntry.php @@ -0,0 +1,34 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class IndexEntry extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + if (!empty($attr['CONTENT'])) { + if (!empty($attr['XREF'])) { + $this->mpdf->IndexEntry(htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES), $attr['XREF']); + return; + } + $objattr = []; + $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES); + $objattr['type'] = 'indexentry'; + $objattr['vertical-align'] = 'T'; + $e = Mpdf::OBJECT_IDENTIFIER . "type=indexentry,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$e]; + } // *TABLES* + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/IndexInsert.php b/src/vendor/mpdf/mpdf/src/Tag/IndexInsert.php new file mode 100644 index 000000000..2704b4fbf --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/IndexInsert.php @@ -0,0 +1,33 @@ +<?php + +namespace Mpdf\Tag; + +class IndexInsert extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $indexCollationLocale = ''; + if (isset($attr['COLLATION'])) { + $indexCollationLocale = $attr['COLLATION']; + } + + $indexCollationGroup = ''; + if (isset($attr['COLLATION-GROUP'])) { + $indexCollationGroup = $attr['COLLATION-GROUP']; + } + + $usedivletters = 1; + if (isset($attr['USEDIVLETTERS']) && (strtoupper($attr['USEDIVLETTERS']) === 'OFF' + || $attr['USEDIVLETTERS'] == -1 + || $attr['USEDIVLETTERS'] === '0')) { + $usedivletters = 0; + } + $links = isset($attr['LINKS']) && (strtoupper($attr['LINKS']) === 'ON' || $attr['LINKS'] == 1); + $this->mpdf->InsertIndex($usedivletters, $links, $indexCollationLocale, $indexCollationGroup); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/InlineTag.php b/src/vendor/mpdf/mpdf/src/Tag/InlineTag.php new file mode 100644 index 000000000..c599f1c6d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/InlineTag.php @@ -0,0 +1,233 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; +use Mpdf\Utils\UtfString; + +abstract class InlineTag extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + + /* -- ANNOTATIONS -- */ + if ($this->mpdf->title2annots && isset($attr['TITLE'])) { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + + $objattr['CONTENT'] = $attr['TITLE']; + $objattr['type'] = 'annot'; + $objattr['POS-X'] = 0; + $objattr['POS-Y'] = 0; + $objattr['ICON'] = 'Comment'; + $objattr['AUTHOR'] = ''; + $objattr['SUBJECT'] = ''; + $objattr['OPACITY'] = $this->mpdf->annotOpacity; + $objattr['COLOR'] = $this->colorConverter->convert('yellow', $this->mpdf->PDFAXwarnings); + $annot = Mpdf::OBJECT_IDENTIFIER . "type=annot,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + } + /* -- END ANNOTATIONS -- */ + + // mPDF 5.7.3 Inline tags + if (!isset($this->mpdf->InlineProperties[$tag])) { + $this->mpdf->InlineProperties[$tag] = [$this->mpdf->saveInlineProperties()]; + } else { + $this->mpdf->InlineProperties[$tag][] = $this->mpdf->saveInlineProperties(); + } + if (isset($annot)) { // *ANNOTATIONS* + if (!isset($this->mpdf->InlineAnnots[$tag])) { + $this->mpdf->InlineAnnots[$tag] = []; + } // *ANNOTATIONS* + $this->mpdf->InlineAnnots[$tag][] = $annot; + } // *ANNOTATIONS* + + $properties = $this->cssManager->MergeCSS('INLINE', $tag, $attr); + if (!empty($properties)) { + $this->mpdf->setCSS($properties, 'INLINE'); + } + + // mPDF 6 Bidirectional formatting for inline elements + $bdf = false; + $bdf2 = ''; + $popd = ''; + + // Get current direction + $currdir = 'ltr'; + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['direction'])) { + $currdir = $this->mpdf->blk[$this->mpdf->blklvl]['direction']; + } + if ($this->mpdf->tableLevel + && isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['direction']) + && $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['direction'] === 'rtl') { + $currdir = 'rtl'; + } + if (isset($attr['DIR']) && $attr['DIR'] != '') { + $currdir = strtolower($attr['DIR']); + } + if (isset($properties['DIRECTION'])) { + $currdir = strtolower($properties['DIRECTION']); + } + + // mPDF 6 bidi + // cf. http://www.w3.org/TR/css3-writing-modes/#unicode-bidi + if ($tag === 'BDO') { + if (isset($attr['DIR']) && strtolower($attr['DIR']) === 'rtl') { + $bdf = 0x202E; + $popd = 'RLOPDF'; + } // U+202E RLO + elseif (isset($attr['DIR']) && strtolower($attr['DIR']) === 'ltr') { + $bdf = 0x202D; + $popd = 'LROPDF'; + } // U+202D LRO + } elseif ($tag === 'BDI') { + if (isset($attr['DIR']) && strtolower($attr['DIR']) === 'rtl') { + $bdf = 0x2067; + $popd = 'RLIPDI'; + } // U+2067 RLI + elseif (isset($attr['DIR']) && strtolower($attr['DIR']) === 'ltr') { + $bdf = 0x2066; + $popd = 'LRIPDI'; + } // U+2066 LRI + else { + $bdf = 0x2068; + $popd = 'FSIPDI'; + } // U+2068 FSI + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'bidi-override') { + if ($currdir === 'rtl') { + $bdf = 0x202E; + $popd = 'RLOPDF'; + } // U+202E RLO + else { + $bdf = 0x202D; + $popd = 'LROPDF'; + } // U+202D LRO + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'embed') { + if ($currdir === 'rtl') { + $bdf = 0x202B; + $popd = 'RLEPDF'; + } // U+202B RLE + else { + $bdf = 0x202A; + $popd = 'LREPDF'; + } // U+202A LRE + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'isolate') { + if ($currdir === 'rtl') { + $bdf = 0x2067; + $popd = 'RLIPDI'; + } // U+2067 RLI + else { + $bdf = 0x2066; + $popd = 'LRIPDI'; + } // U+2066 LRI + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'isolate-override') { + if ($currdir === 'rtl') { + $bdf = 0x2067; + $bdf2 = 0x202E; + $popd = 'RLIRLOPDFPDI'; + } // U+2067 RLI // U+202E RLO + else { + $bdf = 0x2066; + $bdf2 = 0x202D; + $popd = 'LRILROPDFPDI'; + } // U+2066 LRI // U+202D LRO + } elseif (isset($properties ['UNICODE-BIDI']) && strtolower($properties ['UNICODE-BIDI']) === 'plaintext') { + $bdf = 0x2068; + $popd = 'FSIPDI'; // U+2068 FSI + } else { + if (isset($attr['DIR']) && strtolower($attr['DIR']) === 'rtl') { + $bdf = 0x202B; + $popd = 'RLEPDF'; + } // U+202B RLE + elseif (isset($attr['DIR']) && strtolower($attr['DIR']) === 'ltr') { + $bdf = 0x202A; + $popd = 'LREPDF'; + } // U+202A LRE + } + + if ($bdf) { + // mPDF 5.7.3 Inline tags + if (!isset($this->mpdf->InlineBDF[$tag])) { + $this->mpdf->InlineBDF[$tag] = [[$popd, $this->mpdf->InlineBDFctr]]; + } else { + $this->mpdf->InlineBDF[$tag][] = [$popd, $this->mpdf->InlineBDFctr]; + } + $this->mpdf->InlineBDFctr++; + if ($bdf2) { + $bdf2 = UtfString::code2utf($bdf); + } + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer(UtfString::code2utf($bdf) . $bdf2); + } else { + $this->mpdf->_saveTextBuffer(UtfString::code2utf($bdf) . $bdf2); + } + $this->mpdf->biDirectional = true; + } + } + + public function close(&$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + + $annot = false; // mPDF 6 + $bdf = false; // mPDF 6 + + // mPDF 5.7.3 Inline tags + if ($tag === 'PROGRESS' || $tag === 'METER') { + if (!empty($this->mpdf->InlineProperties[$tag])) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties[$tag]); + } + unset($this->mpdf->InlineProperties[$tag]); + if (!empty($this->mpdf->InlineAnnots[$tag])) { + $annot = $this->mpdf->InlineAnnots[$tag]; + } // *ANNOTATIONS* + unset($this->mpdf->InlineAnnots[$tag]); // *ANNOTATIONS* + } else { + if (isset($this->mpdf->InlineProperties[$tag]) && count($this->mpdf->InlineProperties[$tag])) { + $tmpProps = array_pop($this->mpdf->InlineProperties[$tag]); // mPDF 5.7.4 + $this->mpdf->restoreInlineProperties($tmpProps); + } + if (isset($this->mpdf->InlineAnnots[$tag]) && count($this->mpdf->InlineAnnots[$tag])) { // *ANNOTATIONS* + $annot = array_pop($this->mpdf->InlineAnnots[$tag]); // *ANNOTATIONS* + } // *ANNOTATIONS* + if (isset($this->mpdf->InlineBDF[$tag]) && count($this->mpdf->InlineBDF[$tag])) { // mPDF 6 + $bdfarr = array_pop($this->mpdf->InlineBDF[$tag]); + $bdf = $bdfarr[0]; + } + } + + /* -- ANNOTATIONS -- */ + if ($annot) { // mPDF 6 + if ($this->mpdf->tableLevel) { // *TABLES* + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$annot]; // *TABLES* + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$annot]; + } // *TABLES* + } + /* -- END ANNOTATIONS -- */ + + // mPDF 6 bidi + // mPDF 6 Bidirectional formatting for inline elements + if ($bdf) { + $popf = $this->mpdf->_setBidiCodes('end', $bdf); + $this->mpdf->OTLdata = []; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($popf); + } else { + $this->mpdf->_saveTextBuffer($popf); + } + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Input.php b/src/vendor/mpdf/mpdf/src/Tag/Input.php new file mode 100644 index 000000000..bda8bc50f --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Input.php @@ -0,0 +1,430 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; +use Mpdf\Utils\UtfString; + +class Input extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + $this->mpdf->ignorefollowingspaces = false; + if (!isset($attr['TYPE'])) { + $attr['TYPE'] = 'TEXT'; + } + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['type'] = 'input'; + if (isset($attr['DISABLED'])) { + $objattr['disabled'] = true; + } + if (isset($attr['READONLY'])) { + $objattr['readonly'] = true; + } + if (isset($attr['REQUIRED'])) { + $objattr['required'] = true; + } + if (isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK']) === 'true') { + $objattr['spellcheck'] = true; + } + if (isset($attr['TITLE'])) { + $objattr['title'] = $attr['TITLE']; + } elseif (isset($attr['ALT'])) { + $objattr['title'] = $attr['ALT']; + } else { + $objattr['title'] = ''; + } + $objattr['title'] = UtfString::strcode2utf($objattr['title']); + $objattr['title'] = $this->mpdf->lesser_entity_decode($objattr['title']); + if ($this->mpdf->onlyCoreFonts) { + $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mpdf->mb_enc, 'UTF-8'); + } + if ($this->mpdf->useActiveForms && isset($attr['NAME'])) { + $objattr['fieldname'] = $attr['NAME']; + } + if (isset($attr['VALUE'])) { + $attr['VALUE'] = UtfString::strcode2utf($attr['VALUE']); + $attr['VALUE'] = $this->mpdf->lesser_entity_decode($attr['VALUE']); + if ($this->mpdf->onlyCoreFonts) { + $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mpdf->mb_enc, 'UTF-8'); + } + $objattr['value'] = $attr['VALUE']; + } + + $this->mpdf->InlineProperties['INPUT'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('', 'INPUT', $attr); + $objattr['vertical-align'] = ''; + + if (isset($properties['FONT-FAMILY'])) { + $this->mpdf->SetFont($properties['FONT-FAMILY'], $this->mpdf->FontStyle, 0, false); + } + if (isset($properties['FONT-SIZE']) && $properties['FONT-SIZE'] !== 'auto') { + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $this->mpdf->default_font_size / Mpdf::SCALE); + $this->mpdf->SetFontSize($mmsize * Mpdf::SCALE, false); + } + if (isset($properties['COLOR'])) { + $objattr['color'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } + $objattr['fontfamily'] = $this->mpdf->FontFamily; + $objattr['fontsize'] = $this->mpdf->FontSizePt; + if ($this->mpdf->useActiveForms) { + if (isset($attr['ALIGN'])) { + $objattr['text_align'] = $this->getAlign($attr['ALIGN']); + } elseif (isset($properties['TEXT-ALIGN'])) { + $objattr['text_align'] = $this->getAlign($properties['TEXT-ALIGN']); + } + if (isset($properties['BORDER-TOP-COLOR'])) { + $objattr['border-col'] = $this->colorConverter->convert($properties['BORDER-TOP-COLOR'], $this->mpdf->PDFAXwarnings); + } + if (isset($properties['BACKGROUND-COLOR'])) { + $objattr['background-col'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings); + } + } + + $type = ''; + $texto = ''; + $height = $this->mpdf->FontSize; + $width = 0; + $spacesize = $this->mpdf->GetCharWidth(' ', false); + + $w = 0; + if (isset($properties['WIDTH'])) { + $w = $this->sizeConverter->convert($properties['WIDTH'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + } + + if ($properties['VERTICAL-ALIGN']) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + + switch (strtoupper($attr['TYPE'])) { + case 'HIDDEN': + $this->mpdf->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces + if ($this->mpdf->useActiveForms) { + $this->form->SetFormText(0, 0, $objattr['fieldname'], $objattr['value'], $objattr['value'], '', 0, '', true); + } + if ($this->mpdf->InlineProperties[$tag]) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties[$tag]); + } + unset($this->mpdf->InlineProperties[$tag]); + return; + + case 'CHECKBOX': //Draw Checkbox + $type = 'CHECKBOX'; + if (isset($attr['CHECKED'])) { + $objattr['checked'] = true; + } else { + $objattr['checked'] = false; + } + $width = $this->mpdf->FontSize; + $height = $this->mpdf->FontSize; + break; + + case 'RADIO': //Draw Radio button + $type = 'RADIO'; + if (isset($attr['CHECKED'])) { + $objattr['checked'] = true; + } + $width = $this->mpdf->FontSize; + $height = $this->mpdf->FontSize; + break; + + /* -- IMAGES-CORE -- */ + case 'IMAGE': // Draw an Image button + if (isset($attr['SRC'])) { + $type = 'IMAGE'; + $srcpath = $attr['SRC']; + $orig_srcpath = $attr['ORIG_SRC']; + // VSPACE and HSPACE converted to margins in MergeCSS + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-LEFT'])) { + $objattr['margin_left'] = $this->sizeConverter->convert( + $properties['MARGIN-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-RIGHT'])) { + $objattr['margin_right'] = $this->sizeConverter->convert( + $properties['MARGIN-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['BORDER-TOP'])) { + $objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + } + if (isset($properties['BORDER-LEFT'])) { + $objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } + if (isset($properties['BORDER-RIGHT'])) { + $objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } + + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + + if (isset($properties['VERTICAL-ALIGN'])) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + + $w = 0; + $h = 0; + if (isset($properties['WIDTH'])) { + $w = $this->sizeConverter->convert($properties['WIDTH'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + } + if (isset($properties['HEIGHT'])) { + $h = $this->sizeConverter->convert($properties['HEIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + } + + $extraheight = $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w']; + $extrawidth = $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w']; + + // Image file + $info = $this->imageProcessor->getImage($srcpath, true, true, $orig_srcpath); + if (!$info) { + $info = $this->imageProcessor->getImage($this->mpdf->noImageFile); + if ($info) { + $srcpath = $this->mpdf->noImageFile; + $w = ($info['w'] * (25.4 / $this->mpdf->img_dpi)); + $h = ($info['h'] * (25.4 / $this->mpdf->img_dpi)); + } + } + if (!$info) { + break; + } + if ($info['cs'] === 'Indexed') { + $objattr['Indexed'] = true; + } + $objattr['file'] = $srcpath; + //Default width and height calculation if needed + if ($w == 0 && $h == 0) { + /* -- IMAGES-WMF -- */ + if ($info['type'] === 'wmf') { + // WMF units are twips (1/20pt) + // divide by 20 to get points + // divide by k to get user units + $w = abs($info['w']) / (20 * Mpdf::SCALE); + $h = abs($info['h']) / (20 * Mpdf::SCALE); + } else { /* -- END IMAGES-WMF -- */ + if ($info['type'] === 'svg') { + // SVG units are pixels + $w = abs($info['w']) / Mpdf::SCALE; + $h = abs($info['h']) / Mpdf::SCALE; + } else { + //Put image at default image dpi + $w = ($info['w'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi); + $h = ($info['h'] / Mpdf::SCALE) * (72 / $this->mpdf->img_dpi); + } + } + if (isset($properties['IMAGE-RESOLUTION'])) { + if (preg_match('/from-image/i', $properties['IMAGE-RESOLUTION']) && isset($info['set-dpi']) && $info['set-dpi'] > 0) { + $w *= $this->mpdf->img_dpi / $info['set-dpi']; + $h *= $this->mpdf->img_dpi / $info['set-dpi']; + } elseif (preg_match('/(\d+)dpi/i', $properties['IMAGE-RESOLUTION'], $m)) { + $dpi = $m[1]; + if ($dpi > 0) { + $w *= $this->mpdf->img_dpi / $dpi; + $h *= $this->mpdf->img_dpi / $dpi; + } + } + } + } + // IF WIDTH OR HEIGHT SPECIFIED + if ($w == 0) { + $w = $h * $info['w'] / $info['h']; + } + if ($h == 0) { + $h = $w * $info['h'] / $info['w']; + } + // Resize to maximum dimensions of page + $maxWidth = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; + $maxHeight = $this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin + 10); + if ($this->mpdf->fullImageHeight) { + $maxHeight = $this->mpdf->fullImageHeight; + } + if (($w + $extrawidth) > ($maxWidth + 0.0001)) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth + $w = $maxWidth - $extrawidth; + $h = $w * $info['h'] / $info['w']; + } + if ($h + $extraheight > $maxHeight) { + $h = $maxHeight - $extraheight; + $w = $h * $info['w'] / $info['h']; + } + $height = $h + $extraheight; + $width = $w + $extrawidth; + $objattr['type'] = 'image'; + $objattr['itype'] = $info['type']; + $objattr['orig_h'] = $info['h']; + $objattr['orig_w'] = $info['w']; + /* -- IMAGES-WMF -- */ + if ($info['type'] === 'wmf') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + /* -- END IMAGES-WMF -- */ + } else { + if ($info['type'] === 'svg') { + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + } + } + $objattr['height'] = $h + $extraheight; + $objattr['width'] = $w + $extrawidth; + + $objattr['image_height'] = $h; + $objattr['image_width'] = $w; + $objattr['ID'] = $info['i']; + $texto = 'X'; + if ($this->mpdf->useActiveForms) { + if (isset($attr['ONCLICK'])) { + $objattr['onClick'] = $attr['ONCLICK']; + } + $objattr['type'] = 'input'; + $type = 'IMAGE'; + } + break; + } + /* -- END IMAGES-CORE -- */ + + case 'BUTTON': // Draw a button + case 'SUBMIT': + case 'RESET': + $type = strtoupper($attr['TYPE']); + if ($type === 'IMAGE') { + $type = 'BUTTON'; + } // src path not found + if (isset($attr['NOPRINT'])) { + $objattr['noprint'] = true; + } + if (!isset($attr['VALUE'])) { + $objattr['value'] = ucfirst(strtolower($type)); + } + + $texto = ' ' . $objattr['value'] . ' '; + + $width = $this->mpdf->GetStringWidth($texto) + ($this->form->form_element_spacing['button']['outer']['h'] * 2) + + ($this->form->form_element_spacing['button']['inner']['h'] * 2); + + $height = $this->mpdf->FontSize + ($this->form->form_element_spacing['button']['outer']['v'] * 2) + + ($this->form->form_element_spacing['button']['inner']['v'] * 2); + + if ($this->mpdf->useActiveForms && isset($attr['ONCLICK'])) { + $objattr['onClick'] = $attr['ONCLICK']; + } + break; + + case 'PASSWORD': + case 'TEXT': + default: + if ($type == '') { + $type = 'TEXT'; + } + if (strtoupper($attr['TYPE']) === 'PASSWORD') { + $type = 'PASSWORD'; + } + + if ($properties['FONT-SIZE'] === 'auto' && $this->mpdf->useActiveForms) { + $objattr['use_auto_fontsize'] = true; + } + + if (isset($attr['VALUE'])) { + if ($type === 'PASSWORD') { + $num_stars = mb_strlen($attr['VALUE'], $this->mpdf->mb_enc); + $texto = str_repeat('*', $num_stars); + } else { + $texto = $attr['VALUE']; + } + } + $xw = ($this->form->form_element_spacing['input']['outer']['h'] * 2) + ($this->form->form_element_spacing['input']['inner']['h'] * 2); + $xh = ($this->form->form_element_spacing['input']['outer']['v'] * 2) + ($this->form->form_element_spacing['input']['inner']['v'] * 2); + if ($w) { + $width = $w + $xw; + } else { + $width = (20 * $spacesize) + $xw; + } // Default width in chars + if (isset($attr['SIZE']) && ctype_digit($attr['SIZE'])) { + $width = ($attr['SIZE'] * $spacesize) + $xw; + } + $height = $this->mpdf->FontSize + $xh; + if (isset($attr['MAXLENGTH']) && ctype_digit($attr['MAXLENGTH'])) { + $objattr['maxlength'] = $attr['MAXLENGTH']; + } + if ($this->mpdf->useActiveForms) { + if (isset($attr['ONCALCULATE'])) { + $objattr['onCalculate'] = $attr['ONCALCULATE']; + } elseif (isset($attr['ONCHANGE'])) { + $objattr['onCalculate'] = $attr['ONCHANGE']; + } + if (isset($attr['ONVALIDATE'])) { + $objattr['onValidate'] = $attr['ONVALIDATE']; + } + if (isset($attr['ONKEYSTROKE'])) { + $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; + } + if (isset($attr['ONFORMAT'])) { + $objattr['onFormat'] = $attr['ONFORMAT']; + } + } + break; + } + + $objattr['subtype'] = $type; + $objattr['text'] = $texto; + $objattr['width'] = $width; + $objattr['height'] = $height; + $e = Mpdf::OBJECT_IDENTIFIER . "type=input,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + + if ($this->mpdf->InlineProperties[$tag]) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties[$tag]); + } + unset($this->mpdf->InlineProperties[$tag]); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Ins.php b/src/vendor/mpdf/mpdf/src/Tag/Ins.php new file mode 100644 index 000000000..03ec244cc --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Ins.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Ins extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Kbd.php b/src/vendor/mpdf/mpdf/src/Tag/Kbd.php new file mode 100644 index 000000000..10b7880fb --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Kbd.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Kbd extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Legend.php b/src/vendor/mpdf/mpdf/src/Tag/Legend.php new file mode 100644 index 000000000..90308d455 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Legend.php @@ -0,0 +1,35 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Legend extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->InlineProperties['LEGEND'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('INLINE', 'LEGEND', $attr); + if (!empty($properties)) { + $this->mpdf->setCSS($properties, 'INLINE'); + } + } + + public function close(&$ahtml, &$ihtml) + { + if (count($this->mpdf->textbuffer) && !$this->mpdf->tableLevel) { + $leg = $this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1]; + unset($this->mpdf->textbuffer[count($this->mpdf->textbuffer) - 1]); + $this->mpdf->textbuffer = array_values($this->mpdf->textbuffer); + $this->mpdf->blk[$this->mpdf->blklvl]['border_legend'] = $leg; + $this->mpdf->blk[$this->mpdf->blklvl]['margin_top'] += ($leg[11] / 2) / Mpdf::SCALE; + $this->mpdf->blk[$this->mpdf->blklvl]['padding_top'] += ($leg[11] / 2) / Mpdf::SCALE; + } + if (isset($this->mpdf->InlineProperties['LEGEND'])) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['LEGEND']); + } + unset($this->mpdf->InlineProperties['LEGEND']); + $this->mpdf->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Li.php b/src/vendor/mpdf/mpdf/src/Tag/Li.php new file mode 100644 index 000000000..361af06fe --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Li.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Li extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Main.php b/src/vendor/mpdf/mpdf/src/Tag/Main.php new file mode 100644 index 000000000..2e2fe396f --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Main.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Main extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Mark.php b/src/vendor/mpdf/mpdf/src/Tag/Mark.php new file mode 100644 index 000000000..38c14a423 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Mark.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Mark extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Meter.php b/src/vendor/mpdf/mpdf/src/Tag/Meter.php new file mode 100644 index 000000000..a99e8f89a --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Meter.php @@ -0,0 +1,517 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Meter extends InlineTag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + $this->mpdf->inMeter = true; + + $max = 1; + if (!empty($attr['MAX'])) { + $max = $attr['MAX']; + } + + $min = 0; + if (!empty($attr['MIN']) && $tag === 'METER') { + $min = $attr['MIN']; + } + + if ($max < $min) { + $max = $min; + } + + $value = ''; + if (isset($attr['VALUE']) && ($attr['VALUE'] || $attr['VALUE'] === '0')) { + $value = $attr['VALUE']; + if ($value < $min) { + $value = $min; + } elseif ($value > $max) { + $value = $max; + } + } + + $low = $min; + if (!empty($attr['LOW'])) { + $low = $attr['LOW']; + } + if ($low < $min) { + $low = $min; + } elseif ($low > $max) { + $low = $max; + } + $high = $max; + if (!empty($attr['HIGH'])) { + $high = $attr['HIGH']; + } + if ($high < $low) { + $high = $low; + } elseif ($high > $max) { + $high = $max; + } + if (!empty($attr['OPTIMUM'])) { + $optimum = $attr['OPTIMUM']; + } else { + $optimum = $min + (($max - $min) / 2); + } + if ($optimum < $min) { + $optimum = $min; + } elseif ($optimum > $max) { + $optimum = $max; + } + $type = ''; + if (!empty($attr['TYPE'])) { + $type = $attr['TYPE']; + } + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + + $properties = $this->cssManager->MergeCSS('INLINE', $tag, $attr); + if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') { + return; + } + $objattr['visibility'] = 'visible'; + if (isset($properties['VISIBILITY'])) { + $v = strtolower($properties['VISIBILITY']); + if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible') { + $objattr['visibility'] = $v; + } + } + + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-LEFT'])) { + $objattr['margin_left'] = $this->sizeConverter->convert( + $properties['MARGIN-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-RIGHT'])) { + $objattr['margin_right'] = $this->sizeConverter->convert( + $properties['MARGIN-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['PADDING-TOP'])) { + $objattr['padding_top'] = $this->sizeConverter->convert( + $properties['PADDING-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-BOTTOM'])) { + $objattr['padding_bottom'] = $this->sizeConverter->convert( + $properties['PADDING-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-LEFT'])) { + $objattr['padding_left'] = $this->sizeConverter->convert( + $properties['PADDING-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-RIGHT'])) { + $objattr['padding_right'] = $this->sizeConverter->convert( + $properties['PADDING-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['BORDER-TOP'])) { + $objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + } + if (isset($properties['BORDER-LEFT'])) { + $objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } + if (isset($properties['BORDER-RIGHT'])) { + $objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } + + if (isset($properties['VERTICAL-ALIGN'])) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + $w = 0; + $h = 0; + if (isset($properties['WIDTH'])) { + $w = $this->sizeConverter->convert( + $properties['WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['WIDTH'])) { + $w = $this->sizeConverter->convert($attr['WIDTH'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['HEIGHT'])) { + $h = $this->sizeConverter->convert( + $properties['HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } elseif (isset($attr['HEIGHT'])) { + $h = $this->sizeConverter->convert($attr['HEIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { + $objattr['opacity'] = $properties['OPACITY']; + } + if ($this->mpdf->HREF) { + if (strpos($this->mpdf->HREF, '.') === false && strpos($this->mpdf->HREF, '@') !== 0) { + $href = $this->mpdf->HREF; + while (array_key_exists($href, $this->mpdf->internallink)) { + $href = '#' . $href; + } + $this->mpdf->internallink[$href] = $this->mpdf->AddLink(); + $objattr['link'] = $this->mpdf->internallink[$href]; + } else { + $objattr['link'] = $this->mpdf->HREF; + } + } + $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w']; + + $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w']; + + $svg = $this->makeSVG($type, $value, $max, $min, $optimum, $low, $high); + //Save to local file + $srcpath = $this->cache->write('/_tempSVG' . uniqid(random_int(1, 100000), true) . '_' . strtolower($tag) . '.svg', $svg); + $orig_srcpath = $srcpath; + $this->mpdf->GetFullPath($srcpath); + + $info = $this->imageProcessor->getImage($srcpath, true, true, $orig_srcpath); + if (!$info) { + $info = $this->imageProcessor->getImage($this->mpdf->noImageFile); + if ($info) { + $srcpath = $this->mpdf->noImageFile; + $w = ($info['w'] * (25.4 / $this->mpdf->img_dpi)); + $h = ($info['h'] * (25.4 / $this->mpdf->img_dpi)); + } + } + if (!$info) { + return; + } + + $objattr['file'] = $srcpath; + + // Default width and height calculation if needed + if ($w == 0 && $h == 0) { + // SVG units are pixels + $w = $this->mpdf->FontSize / (10 / Mpdf::SCALE) * abs($info['w']) / Mpdf::SCALE; + $h = $this->mpdf->FontSize / (10 / Mpdf::SCALE) * abs($info['h']) / Mpdf::SCALE; + } + + // IF WIDTH OR HEIGHT SPECIFIED + if ($w == 0) { + $w = $info['h'] ? abs($h * $info['w'] / $info['h']) : INF; + } + if ($h == 0) { + $h = $info['w'] ? abs($w * $info['h'] / $info['w']) : INF; + } + + // Resize to maximum dimensions of page + $maxWidth = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; + $maxHeight = $this->mpdf->h - ($this->mpdf->tMargin + $this->mpdf->bMargin + 1); + if ($this->mpdf->fullImageHeight) { + $maxHeight = $this->mpdf->fullImageHeight; + } + if (($w + $extrawidth) > ($maxWidth + 0.0001)) { // mPDF 5.7.4 0.0001 to allow for rounding errors when w==maxWidth + $w = $maxWidth - $extrawidth; + $h = abs($w * $info['h'] / $info['w']); + } + + if ($h + $extraheight > $maxHeight) { + $h = $maxHeight - $extraheight; + $w = abs($h * $info['w'] / $info['h']); + } + $objattr['type'] = 'image'; + $objattr['itype'] = $info['type']; + + $objattr['orig_h'] = $info['h']; + $objattr['orig_w'] = $info['w']; + $objattr['wmf_x'] = $info['x']; + $objattr['wmf_y'] = $info['y']; + $objattr['height'] = $h + $extraheight; + $objattr['width'] = $w + $extrawidth; + $objattr['image_height'] = $h; + $objattr['image_width'] = $w; + $e = Mpdf::OBJECT_IDENTIFIER . "type=image,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; + } else { + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } + } + + public function close(&$ahtml, &$ihtml) + { + parent::close($ahtml, $ihtml); + $this->mpdf->ignorefollowingspaces = false; + $this->mpdf->inMeter = false; + } + + protected function makeSVG($type, $value, $max, $min, $optimum, $low, $high) + { + if ($type == '2') { + ///////////////////////////////////////////////////////////////////////////////////// + ///////// CUSTOM <meter type="2"> + ///////////////////////////////////////////////////////////////////////////////////// + $h = 10; + $w = 160; + $border_radius = 0.143; // Factor of Height + + $svg = '<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="' . $w . 'px" height="' . $h . 'px" viewBox="0 0 ' . $w . ' ' . $h . '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><g> + + +<defs> +<linearGradient id="GrGRAY" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(222, 222, 222)" /> +<stop offset="20%" stop-color="rgb(232, 232, 232)" /> +<stop offset="25%" stop-color="rgb(232, 232, 232)" /> +<stop offset="100%" stop-color="rgb(182, 182, 182)" /> +</linearGradient> + +</defs> +'; + $svg .= '<rect x="0" y="0" width="' . $w . '" height="' . $h . '" fill="#f4f4f4" stroke="none" />'; + + // LOW to HIGH region + //if ($low && $high && ($low != $min || $high != $max)) { + if ($low && $high) { + $barx = (($low - $min) / ($max - $min) ) * $w; + $barw = (($high - $low) / ($max - $min) ) * $w; + $svg .= '<rect x="' . $barx . '" y="0" width="' . $barw . '" height="' . $h . '" fill="url(#GrGRAY)" stroke="#888888" stroke-width="0.5px" />'; + } + + // OPTIMUM Marker (? AVERAGE) + if ($optimum) { + $barx = (($optimum - $min) / ($max - $min) ) * $w; + $barw = $h / 2; + $barcol = '#888888'; + $svg .= '<rect x="' . $barx . '" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $barw . '" height="' . $h . '" fill="' . $barcol . '" stroke="none" />'; + } + + // VALUE Marker + if ($value) { + if ($min != $low && $value < $low) { + $col = 'orange'; + } elseif ($max != $high && $value > $high) { + $col = 'orange'; + } else { + $col = '#008800'; + } + $cx = (($value - $min) / ($max - $min) ) * $w; + $cy = $h / 2; + $rx = $h / 3.5; + $ry = $h / 2.2; + $svg .= '<ellipse fill="' . $col . '" stroke="#000000" stroke-width="0.5px" cx="' . $cx . '" cy="' . $cy . '" rx="' . $rx . '" ry="' . $ry . '"/>'; + } + + // BoRDER + $svg .= '<rect x="0" y="0" width="' . $w . '" height="' . $h . '" fill="none" stroke="#888888" stroke-width="0.5px" />'; + + $svg .= '</g></svg>'; + } elseif ($type == '3') { + ///////////////////////////////////////////////////////////////////////////////////// + ///////// CUSTOM <meter type="2"> + ///////////////////////////////////////////////////////////////////////////////////// + $h = 10; + $w = 100; + $border_radius = 0.143; // Factor of Height + + $svg = '<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="' . $w . 'px" height="' . $h . 'px" viewBox="0 0 ' . $w . ' ' . $h . '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><g> + + +<defs> +<linearGradient id="GrGRAY" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(222, 222, 222)" /> +<stop offset="20%" stop-color="rgb(232, 232, 232)" /> +<stop offset="25%" stop-color="rgb(232, 232, 232)" /> +<stop offset="100%" stop-color="rgb(182, 182, 182)" /> +</linearGradient> + +</defs> +'; + $svg .= '<rect x="0" y="0" width="' . $w . '" height="' . $h . '" fill="#f4f4f4" stroke="none" />'; + + // LOW to HIGH region + if ($low && $high && ($low != $min || $high != $max)) { + //if ($low && $high) { + $barx = (($low - $min) / ($max - $min) ) * $w; + $barw = (($high - $low) / ($max - $min) ) * $w; + $svg .= '<rect x="' . $barx . '" y="0" width="' . $barw . '" height="' . $h . '" fill="url(#GrGRAY)" stroke="#888888" stroke-width="0.5px" />'; + } + + // OPTIMUM Marker (? AVERAGE) + if ($optimum) { + $barx = (($optimum - $min) / ($max - $min) ) * $w; + $barw = $h / 2; + $barcol = '#888888'; + $svg .= '<rect x="' . $barx . '" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $barw . '" height="' . $h . '" fill="' . $barcol . '" stroke="none" />'; + } + + // VALUE Marker + if ($value) { + if ($min != $low && $value < $low) { + $col = 'orange'; + } elseif ($max != $high && $value > $high) { + $col = 'orange'; + } else { + $col = 'orange'; + } + $cx = (($value - $min) / ($max - $min) ) * $w; + $cy = $h / 2; + $rx = $h / 2.2; + $ry = $h / 2.2; + $svg .= '<ellipse fill="' . $col . '" stroke="#000000" stroke-width="0.5px" cx="' . $cx . '" cy="' . $cy . '" rx="' . $rx . '" ry="' . $ry . '"/>'; + } + + // BoRDER + $svg .= '<rect x="0" y="0" width="' . $w . '" height="' . $h . '" fill="none" stroke="#888888" stroke-width="0.5px" />'; + + $svg .= '</g></svg>'; + } else { + ///////////////////////////////////////////////////////////////////////////////////// + ///////// DEFAULT <meter> + ///////////////////////////////////////////////////////////////////////////////////// + $h = 10; + $w = 50; + $border_radius = 0.143; // Factor of Height + + $svg = '<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="' . $w . 'px" height="' . $h . 'px" viewBox="0 0 ' . $w . ' ' . $h . '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><g> + +<defs> +<linearGradient id="GrGRAY" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(222, 222, 222)" /> +<stop offset="20%" stop-color="rgb(232, 232, 232)" /> +<stop offset="25%" stop-color="rgb(232, 232, 232)" /> +<stop offset="100%" stop-color="rgb(182, 182, 182)" /> +</linearGradient> + +<linearGradient id="GrRED" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(255, 162, 162)" /> +<stop offset="20%" stop-color="rgb(255, 218, 218)" /> +<stop offset="25%" stop-color="rgb(255, 218, 218)" /> +<stop offset="100%" stop-color="rgb(255, 0, 0)" /> +</linearGradient> + +<linearGradient id="GrGREEN" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(102, 230, 102)" /> +<stop offset="20%" stop-color="rgb(218, 255, 218)" /> +<stop offset="25%" stop-color="rgb(218, 255, 218)" /> +<stop offset="100%" stop-color="rgb(0, 148, 0)" /> +</linearGradient> + +<linearGradient id="GrBLUE" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(102, 102, 230)" /> +<stop offset="20%" stop-color="rgb(238, 238, 238)" /> +<stop offset="25%" stop-color="rgb(238, 238, 238)" /> +<stop offset="100%" stop-color="rgb(0, 0, 128)" /> +</linearGradient> + +<linearGradient id="GrORANGE" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(255, 186, 0)" /> +<stop offset="20%" stop-color="rgb(255, 238, 168)" /> +<stop offset="25%" stop-color="rgb(255, 238, 168)" /> +<stop offset="100%" stop-color="rgb(255, 155, 0)" /> +</linearGradient> +</defs> + +<rect x="0" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $w . '" height="' . $h . '" fill="url(#GrGRAY)" stroke="none" /> +'; + + if ($value) { + $barw = (($value - $min) / ($max - $min) ) * $w; + if ($optimum < $low) { + if ($value < $low) { + $barcol = 'url(#GrGREEN)'; + } elseif ($value > $high) { + $barcol = 'url(#GrRED)'; + } else { + $barcol = 'url(#GrORANGE)'; + } + } elseif ($optimum > $high) { + if ($value < $low) { + $barcol = 'url(#GrRED)'; + } elseif ($value > $high) { + $barcol = 'url(#GrGREEN)'; + } else { + $barcol = 'url(#GrORANGE)'; + } + } else { + if ($value < $low) { + $barcol = 'url(#GrORANGE)'; + } elseif ($value > $high) { + $barcol = 'url(#GrORANGE)'; + } else { + $barcol = 'url(#GrGREEN)'; + } + } + $svg .= '<rect x="0" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $barw . '" height="' . $h . '" fill="' . $barcol . '" stroke="none" />'; + } + + $svg .= '</g></svg>'; + } + + + return $svg; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Nav.php b/src/vendor/mpdf/mpdf/src/Tag/Nav.php new file mode 100644 index 000000000..7845cfa5d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Nav.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Nav extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/NewColumn.php b/src/vendor/mpdf/mpdf/src/Tag/NewColumn.php new file mode 100644 index 000000000..a9ff5a1bf --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/NewColumn.php @@ -0,0 +1,18 @@ +<?php + +namespace Mpdf\Tag; + +class NewColumn extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->ignorefollowingspaces = true; + $this->mpdf->NewColumn(); + $this->mpdf->ColumnAdjust = false; // disables all column height adjustment for the page. + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/NewPage.php b/src/vendor/mpdf/mpdf/src/Tag/NewPage.php new file mode 100644 index 000000000..3a7f50f22 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/NewPage.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf\Tag; + +class NewPage extends FormFeed +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Ol.php b/src/vendor/mpdf/mpdf/src/Tag/Ol.php new file mode 100644 index 000000000..75deba9a3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Ol.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Ol extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Option.php b/src/vendor/mpdf/mpdf/src/Tag/Option.php new file mode 100644 index 000000000..04221d0f4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Option.php @@ -0,0 +1,39 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Utils\UtfString; + +class Option extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = ''; + $this->mpdf->selectoption['ACTIVE'] = true; + $this->mpdf->selectoption['currentSEL'] = false; + if (empty($this->mpdf->selectoption)) { + $this->mpdf->selectoption['MAXWIDTH'] = ''; + $this->mpdf->selectoption['SELECTED'] = ''; + } + if (isset($attr['SELECTED'])) { + $this->mpdf->selectoption['SELECTED'] = ''; + $this->mpdf->selectoption['currentSEL'] = true; + } + if (isset($attr['VALUE'])) { + $attr['VALUE'] = UtfString::strcode2utf($attr['VALUE']); + $attr['VALUE'] = $this->mpdf->lesser_entity_decode($attr['VALUE']); + if ($this->mpdf->onlyCoreFonts) { + $attr['VALUE'] = mb_convert_encoding($attr['VALUE'], $this->mpdf->mb_enc, 'UTF-8'); + } + } + + $this->mpdf->selectoption['currentVAL'] = isset($attr['VALUE']) ? $attr['VALUE'] : $ahtml[$ihtml + 1]; + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->selectoption['ACTIVE'] = false; + $this->mpdf->lastoptionaltag = ''; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/P.php b/src/vendor/mpdf/mpdf/src/Tag/P.php new file mode 100644 index 000000000..61b2a80c0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/P.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class P extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/PageBreak.php b/src/vendor/mpdf/mpdf/src/Tag/PageBreak.php new file mode 100644 index 000000000..9f721c4b5 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/PageBreak.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf\Tag; + +class PageBreak extends FormFeed +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/PageFooter.php b/src/vendor/mpdf/mpdf/src/Tag/PageFooter.php new file mode 100644 index 000000000..7b18a617b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/PageFooter.php @@ -0,0 +1,153 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class PageFooter extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + $this->mpdf->ignorefollowingspaces = true; + $pname = '_nonhtmldefault'; + if ($attr['NAME']) { + $pname = $attr['NAME']; + } // mPDF 6 + + $p = []; // mPDF 6 + $p['L'] = []; + $p['C'] = []; + $p['R'] = []; + $p['L']['font-style'] = ''; + $p['C']['font-style'] = ''; + $p['R']['font-style'] = ''; + + if (isset($attr['CONTENT-LEFT'])) { + $p['L']['content'] = $attr['CONTENT-LEFT']; + } + if (isset($attr['CONTENT-CENTER'])) { + $p['C']['content'] = $attr['CONTENT-CENTER']; + } + if (isset($attr['CONTENT-RIGHT'])) { + $p['R']['content'] = $attr['CONTENT-RIGHT']; + } + + if (isset($attr['HEADER-STYLE']) || isset($attr['FOOTER-STYLE'])) { // font-family,size,weight,style,color + if ($tag === 'PAGEHEADER') { + $properties = $this->cssManager->readInlineCSS($attr['HEADER-STYLE']); + } else { + $properties = $this->cssManager->readInlineCSS($attr['FOOTER-STYLE']); + } + if (isset($properties['FONT-FAMILY'])) { + $p['L']['font-family'] = $properties['FONT-FAMILY']; + $p['C']['font-family'] = $properties['FONT-FAMILY']; + $p['R']['font-family'] = $properties['FONT-FAMILY']; + } + if (isset($properties['FONT-SIZE'])) { + $p['L']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + $p['C']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + $p['R']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + } + if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT'] === 'bold') { + $p['L']['font-style'] = 'B'; + $p['C']['font-style'] = 'B'; + $p['R']['font-style'] = 'B'; + } + if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE'] === 'italic') { + $p['L']['font-style'] .= 'I'; + $p['C']['font-style'] .= 'I'; + $p['R']['font-style'] .= 'I'; + } + if (isset($properties['COLOR'])) { + $p['L']['color'] = $properties['COLOR']; + $p['C']['color'] = $properties['COLOR']; + $p['R']['color'] = $properties['COLOR']; + } + } + if (isset($attr['HEADER-STYLE-LEFT']) || isset($attr['FOOTER-STYLE-LEFT'])) { + if ($tag === 'PAGEHEADER') { + $properties = $this->cssManager->readInlineCSS($attr['HEADER-STYLE-LEFT']); + } else { + $properties = $this->cssManager->readInlineCSS($attr['FOOTER-STYLE-LEFT']); + } + if (isset($properties['FONT-FAMILY'])) { + $p['L']['font-family'] = $properties['FONT-FAMILY']; + } + if (isset($properties['FONT-SIZE'])) { + $p['L']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + } + if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT'] === 'bold') { + $p['L']['font-style'] = 'B'; + } + if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE'] === 'italic') { + $p['L']['font-style'] .='I'; + } + if (isset($properties['COLOR'])) { + $p['L']['color'] = $properties['COLOR']; + } + } + if (isset($attr['HEADER-STYLE-CENTER']) || isset($attr['FOOTER-STYLE-CENTER'])) { + if ($tag === 'PAGEHEADER') { + $properties = $this->cssManager->readInlineCSS($attr['HEADER-STYLE-CENTER']); + } else { + $properties = $this->cssManager->readInlineCSS($attr['FOOTER-STYLE-CENTER']); + } + if (isset($properties['FONT-FAMILY'])) { + $p['C']['font-family'] = $properties['FONT-FAMILY']; + } + if (isset($properties['FONT-SIZE'])) { + $p['C']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + } + if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT'] === 'bold') { + $p['C']['font-style'] = 'B'; + } + if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE'] === 'italic') { + $p['C']['font-style'] .= 'I'; + } + if (isset($properties['COLOR'])) { + $p['C']['color'] = $properties['COLOR']; + } + } + if (isset($attr['HEADER-STYLE-RIGHT']) || isset($attr['FOOTER-STYLE-RIGHT'])) { + if ($tag === 'PAGEHEADER') { + $properties = $this->cssManager->readInlineCSS($attr['HEADER-STYLE-RIGHT']); + } else { + $properties = $this->cssManager->readInlineCSS($attr['FOOTER-STYLE-RIGHT']); + } + if (isset($properties['FONT-FAMILY'])) { + $p['R']['font-family'] = $properties['FONT-FAMILY']; + } + if (isset($properties['FONT-SIZE'])) { + $p['R']['font-size'] = $this->sizeConverter->convert($properties['FONT-SIZE']) * Mpdf::SCALE; + } + if (isset($properties['FONT-WEIGHT']) && $properties['FONT-WEIGHT'] === 'bold') { + $p['R']['font-style'] = 'B'; + } + if (isset($properties['FONT-STYLE']) && $properties['FONT-STYLE'] === 'italic') { + $p['R']['font-style'] .= 'I'; + } + if (isset($properties['COLOR'])) { + $p['R']['color'] = $properties['COLOR']; + } + } + if (!empty($attr['LINE'])) { // 0|1|on|off + $lineset = 0; + if ($attr['LINE'] == '1' || strtoupper($attr['LINE']) === 'ON') { + $lineset = 1; + } + $p['line'] = $lineset; + } + // mPDF 6 + if ($tag === 'PAGEHEADER') { + $this->mpdf->DefHeaderByName($pname, $p); + } else { + $this->mpdf->DefFooterByName($pname, $p); + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/PageHeader.php b/src/vendor/mpdf/mpdf/src/Tag/PageHeader.php new file mode 100644 index 000000000..9920ee789 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/PageHeader.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf\Tag; + +class PageHeader extends PageFooter +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Pre.php b/src/vendor/mpdf/mpdf/src/Tag/Pre.php new file mode 100644 index 000000000..ef21606ea --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Pre.php @@ -0,0 +1,13 @@ +<?php + +namespace Mpdf\Tag; + +class Pre extends BlockTag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->ispre = true; // ADDED - Prevents left trim of textbuffer in printbuffer() + parent::open($attr, $ahtml, $ihtml); // TODO: Change the autogenerated stub + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Progress.php b/src/vendor/mpdf/mpdf/src/Tag/Progress.php new file mode 100644 index 000000000..32e22daa0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Progress.php @@ -0,0 +1,72 @@ +<?php + +namespace Mpdf\Tag; + +class Progress extends Meter +{ + protected function makeSVG($type, $value, $max, $min, $optimum, $low, $high) + { + $svg = ''; + + if ($type == '2') { + ///////////////////////////////////////////////////////////////////////////////////// + ///////// CUSTOM <progress type="2"> + ///////////////////////////////////////////////////////////////////////////////////// + } else { + ///////////////////////////////////////////////////////////////////////////////////// + ///////// DEFAULT <progress> + ///////////////////////////////////////////////////////////////////////////////////// + $h = 10; + $w = 100; + $border_radius = 0.143; // Factor of Height + + if ($value or $value === '0') { + $fill = 'url(#GrGRAY)'; + } else { + $fill = '#f8f8f8'; + } + + $svg = '<svg width="' . $w . 'px" height="' . $h . 'px" viewBox="0 0 ' . $w . ' ' . $h . '"><g> + +<defs> +<linearGradient id="GrGRAY" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(222, 222, 222)" /> +<stop offset="20%" stop-color="rgb(232, 232, 232)" /> +<stop offset="25%" stop-color="rgb(232, 232, 232)" /> +<stop offset="100%" stop-color="rgb(182, 182, 182)" /> +</linearGradient> + +<linearGradient id="GrGREEN" x1="0" y1="0" x2="0" y2="1" gradientUnits="boundingBox"> +<stop offset="0%" stop-color="rgb(102, 230, 102)" /> +<stop offset="20%" stop-color="rgb(218, 255, 218)" /> +<stop offset="25%" stop-color="rgb(218, 255, 218)" /> +<stop offset="100%" stop-color="rgb(0, 148, 0)" /> +</linearGradient> + +</defs> + +<rect x="0" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $w . '" height="' . $h . '" fill="' . $fill . '" stroke="none" /> +'; + + if ($value) { + $barw = (($value - $min) / ($max - $min) ) * $w; + $barcol = 'url(#GrGREEN)'; + $svg .= '<rect x="0" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $barw . '" height="' . $h . '" fill="' . $barcol . '" stroke="none" />'; + } + + + // Borders + $svg .= '<rect x="0" y="0" rx="' . ($h * $border_radius) . 'px" ry="' . ($h * $border_radius) . 'px" width="' . $w . '" height="' . $h . '" fill="none" stroke="#888888" stroke-width="0.5px" />'; + if ($value) { + // $svg .= '<rect x="0" y="0" rx="'.($h*$border_radius).'px" ry="'.($h*$border_radius).'px" width="'.$barw.'" height="'.$h.'" fill="none" stroke="#888888" stroke-width="0.5px" />'; + } + + + $svg .= '</g></svg>'; + } + + + return $svg; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Q.php b/src/vendor/mpdf/mpdf/src/Tag/Q.php new file mode 100644 index 000000000..3e0567412 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Q.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Q extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/S.php b/src/vendor/mpdf/mpdf/src/Tag/S.php new file mode 100644 index 000000000..37aa8327b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/S.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class S extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Samp.php b/src/vendor/mpdf/mpdf/src/Tag/Samp.php new file mode 100644 index 000000000..c541cdd8e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Samp.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Samp extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Section.php b/src/vendor/mpdf/mpdf/src/Tag/Section.php new file mode 100644 index 000000000..1c41a7b0c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Section.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Section extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Select.php b/src/vendor/mpdf/mpdf/src/Tag/Select.php new file mode 100644 index 000000000..60addcb77 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Select.php @@ -0,0 +1,154 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class Select extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = ''; // Save current HTML specified optional endtag + $this->mpdf->InlineProperties['SELECT'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('', 'SELECT', $attr); + if (isset($properties['FONT-FAMILY'])) { + $this->mpdf->SetFont($properties['FONT-FAMILY'], $this->mpdf->FontStyle, 0, false); + } + if (isset($properties['FONT-SIZE'])) { + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $this->mpdf->default_font_size / Mpdf::SCALE); + $this->mpdf->SetFontSize($mmsize * Mpdf::SCALE, false); + } + if (isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK']) === 'true') { + $this->mpdf->selectoption['SPELLCHECK'] = true; + } + + if (isset($properties['COLOR'])) { + $this->mpdf->selectoption['COLOR'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } + $this->mpdf->specialcontent = 'type=select'; + if (isset($attr['DISABLED'])) { + $this->mpdf->selectoption['DISABLED'] = $attr['DISABLED']; + } + if (isset($attr['READONLY'])) { + $this->mpdf->selectoption['READONLY'] = $attr['READONLY']; + } + if (isset($attr['REQUIRED'])) { + $this->mpdf->selectoption['REQUIRED'] = $attr['REQUIRED']; + } + if (isset($attr['EDITABLE'])) { + $this->mpdf->selectoption['EDITABLE'] = $attr['EDITABLE']; + } + if (isset($attr['TITLE'])) { + $this->mpdf->selectoption['TITLE'] = $attr['TITLE']; + } + if (isset($attr['MULTIPLE'])) { + $this->mpdf->selectoption['MULTIPLE'] = $attr['MULTIPLE']; + } + if (isset($attr['SIZE']) && $attr['SIZE'] > 1) { + $this->mpdf->selectoption['SIZE'] = $attr['SIZE']; + } + if ($this->mpdf->useActiveForms) { + if (isset($attr['NAME'])) { + $this->mpdf->selectoption['NAME'] = $attr['NAME']; + } + if (isset($attr['ONCHANGE'])) { + $this->mpdf->selectoption['ONCHANGE'] = $attr['ONCHANGE']; + } + } + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->ignorefollowingspaces = false; + $this->mpdf->lastoptionaltag = ''; + $texto = ''; + $OTLdata = false; + if (isset($this->mpdf->selectoption['SELECTED'])) { + $texto = $this->mpdf->selectoption['SELECTED']; + } + if (isset($this->mpdf->selectoption['SELECTED-OTLDATA'])) { + $OTLdata = $this->mpdf->selectoption['SELECTED-OTLDATA']; + } + + if ($this->mpdf->useActiveForms) { + $w = $this->mpdf->selectoption['MAXWIDTH']; + } else { + $w = $this->mpdf->GetStringWidth($texto, true, $OTLdata); + } + if ($w == 0) { + $w = 5; + } + $objattr['type'] = 'select'; + $objattr['text'] = $texto; + $objattr['OTLdata'] = $OTLdata; + if (isset($this->mpdf->selectoption['NAME'])) { + $objattr['fieldname'] = $this->mpdf->selectoption['NAME']; + } + if (isset($this->mpdf->selectoption['READONLY'])) { + $objattr['readonly'] = true; + } + if (isset($this->mpdf->selectoption['REQUIRED'])) { + $objattr['required'] = true; + } + if (isset($this->mpdf->selectoption['SPELLCHECK'])) { + $objattr['spellcheck'] = true; + } + if (isset($this->mpdf->selectoption['EDITABLE'])) { + $objattr['editable'] = true; + } + if (isset($this->mpdf->selectoption['ONCHANGE'])) { + $objattr['onChange'] = $this->mpdf->selectoption['ONCHANGE']; + } + if (isset($this->mpdf->selectoption['ITEMS'])) { + $objattr['items'] = $this->mpdf->selectoption['ITEMS']; + } + if (isset($this->mpdf->selectoption['MULTIPLE'])) { + $objattr['multiple'] = $this->mpdf->selectoption['MULTIPLE']; + } + if (isset($this->mpdf->selectoption['DISABLED'])) { + $objattr['disabled'] = $this->mpdf->selectoption['DISABLED']; + } + if (isset($this->mpdf->selectoption['TITLE'])) { + $objattr['title'] = $this->mpdf->selectoption['TITLE']; + } + if (isset($this->mpdf->selectoption['COLOR'])) { + $objattr['color'] = $this->mpdf->selectoption['COLOR']; + } + if (isset($this->mpdf->selectoption['SIZE'])) { + $objattr['size'] = $this->mpdf->selectoption['SIZE']; + } + $rows = 1; + if (isset($objattr['size']) && $objattr['size'] > 1) { + $rows = $objattr['size']; + } + + $objattr['fontfamily'] = $this->mpdf->FontFamily; + $objattr['fontsize'] = $this->mpdf->FontSizePt; + + $objattr['width'] = $w + ($this->form->form_element_spacing['select']['outer']['h'] * 2) + + ($this->form->form_element_spacing['select']['inner']['h'] * 2) + ($this->mpdf->FontSize * 1.4); + + $objattr['height'] = ($this->mpdf->FontSize * $rows) + ($this->form->form_element_spacing['select']['outer']['v'] * 2) + + ($this->form->form_element_spacing['select']['inner']['v'] * 2); + + $e = Mpdf::OBJECT_IDENTIFIER . "type=select,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + // Output it to buffers + if ($this->mpdf->tableLevel) { // *TABLES* + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; // *TABLES* + } // *TABLES* + else { // *TABLES* + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + + $this->mpdf->selectoption = []; + $this->mpdf->specialcontent = ''; + + if ($this->mpdf->InlineProperties['SELECT']) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['SELECT']); + } + unset($this->mpdf->InlineProperties['SELECT']); + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageFooter.php b/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageFooter.php new file mode 100644 index 000000000..6cb524245 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageFooter.php @@ -0,0 +1,73 @@ +<?php + +namespace Mpdf\Tag; + +class SetHtmlPageFooter extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + $this->mpdf->ignorefollowingspaces = true; + + $pname = '_default'; + if (!empty($attr['NAME'])) { + $pname = $attr['NAME']; + } elseif ($tag === 'SETPAGEHEADER' || $tag === 'SETPAGEFOOTER') { + $pname = '_nonhtmldefault'; + } // mPDF 6 + + if (!empty($attr['PAGE'])) { // O|odd|even|E|ALL|[blank] + $side = 'odd'; + if (strtoupper($attr['PAGE']) === 'O' || strtoupper($attr['PAGE']) === 'ODD') { + $side = 'odd'; + } elseif (strtoupper($attr['PAGE']) === 'E' || strtoupper($attr['PAGE']) === 'EVEN') { + $side = 'even'; + } elseif (strtoupper($attr['PAGE']) === 'ALL') { + $side = 'both'; + } + } else { + $side = 'odd'; + } + if (!empty($attr['VALUE'])) { // -1|1|on|off + $set = 1; + if ($attr['VALUE'] == '1' || strtoupper($attr['VALUE']) === 'ON') { + $set = 1; + } elseif ($attr['VALUE'] == '-1' || strtoupper($attr['VALUE']) === 'OFF') { + $set = 0; + } + } else { + $set = 1; + } + $write = 0; + if (!empty($attr['SHOW-THIS-PAGE']) && ($tag === 'SETHTMLPAGEHEADER' || $tag === 'SETPAGEHEADER')) { + $write = 1; + } + if ($side === 'odd' || $side === 'both') { + if ($set && ($tag === 'SETHTMLPAGEHEADER' || $tag === 'SETPAGEHEADER')) { + $this->mpdf->SetHTMLHeader($this->mpdf->pageHTMLheaders[$pname], 'O', $write); + } elseif ($set && ($tag === 'SETHTMLPAGEFOOTER' || $tag === 'SETPAGEFOOTER')) { + $this->mpdf->SetHTMLFooter($this->mpdf->pageHTMLfooters[$pname], 'O'); + } elseif ($tag === 'SETHTMLPAGEHEADER' || $tag === 'SETPAGEHEADER') { + $this->mpdf->SetHTMLHeader('', 'O'); + } else { + $this->mpdf->SetHTMLFooter('', 'O'); + } + } + if ($side === 'even' || $side === 'both') { + if ($set && ($tag === 'SETHTMLPAGEHEADER' || $tag === 'SETPAGEHEADER')) { + $this->mpdf->SetHTMLHeader($this->mpdf->pageHTMLheaders[$pname], 'E', $write); + } elseif ($set && ($tag === 'SETHTMLPAGEFOOTER' || $tag === 'SETPAGEFOOTER')) { + $this->mpdf->SetHTMLFooter($this->mpdf->pageHTMLfooters[$pname], 'E'); + } elseif ($tag === 'SETHTMLPAGEHEADER' || $tag === 'SETPAGEHEADER') { + $this->mpdf->SetHTMLHeader('', 'E'); + } else { + $this->mpdf->SetHTMLFooter('', 'E'); + } + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageHeader.php b/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageHeader.php new file mode 100644 index 000000000..ea987838b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/SetHtmlPageHeader.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class SetHtmlPageHeader extends SetHtmlPageFooter +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/SetPageFooter.php b/src/vendor/mpdf/mpdf/src/Tag/SetPageFooter.php new file mode 100644 index 000000000..7596c80a7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/SetPageFooter.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class SetPageFooter extends SetHtmlPageFooter +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/SetPageHeader.php b/src/vendor/mpdf/mpdf/src/Tag/SetPageHeader.php new file mode 100644 index 000000000..ff83dbc3c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/SetPageHeader.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class SetPageHeader extends SetHtmlPageFooter +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Small.php b/src/vendor/mpdf/mpdf/src/Tag/Small.php new file mode 100644 index 000000000..686c1ebe4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Small.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Small extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Span.php b/src/vendor/mpdf/mpdf/src/Tag/Span.php new file mode 100644 index 000000000..eaa3c6a16 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Span.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Span extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Strike.php b/src/vendor/mpdf/mpdf/src/Tag/Strike.php new file mode 100644 index 000000000..65ae0f818 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Strike.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Strike extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Strong.php b/src/vendor/mpdf/mpdf/src/Tag/Strong.php new file mode 100644 index 000000000..5592c3d04 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Strong.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Strong extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Sub.php b/src/vendor/mpdf/mpdf/src/Tag/Sub.php new file mode 100644 index 000000000..66a99e16d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Sub.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Sub extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/SubstituteTag.php b/src/vendor/mpdf/mpdf/src/Tag/SubstituteTag.php new file mode 100644 index 000000000..602aa5178 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/SubstituteTag.php @@ -0,0 +1,18 @@ +<?php + +namespace Mpdf\Tag; + +abstract class SubstituteTag extends Tag +{ + + public function close(&$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + if ($this->mpdf->InlineProperties[$tag]) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties[$tag]); + } + unset($this->mpdf->InlineProperties[$tag]); + $ltag = strtolower($tag); + $this->mpdf->$ltag = false; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Summary.php b/src/vendor/mpdf/mpdf/src/Tag/Summary.php new file mode 100644 index 000000000..977cc44a0 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Summary.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Summary extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Sup.php b/src/vendor/mpdf/mpdf/src/Tag/Sup.php new file mode 100644 index 000000000..97221655a --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Sup.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Sup extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TBody.php b/src/vendor/mpdf/mpdf/src/Tag/TBody.php new file mode 100644 index 000000000..25b4c4531 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TBody.php @@ -0,0 +1,23 @@ +<?php + +namespace Mpdf\Tag; + +class TBody extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->tablethead = 0; + $this->mpdf->tabletfoot = 0; + $this->mpdf->lastoptionaltag = 'TBODY'; // Save current HTML specified optional endtag + $this->cssManager->tbCSSlvl++; + $this->cssManager->MergeCSS('TABLE', 'TBODY', $attr); + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = ''; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TFoot.php b/src/vendor/mpdf/mpdf/src/Tag/TFoot.php new file mode 100644 index 000000000..d3bd8e80a --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TFoot.php @@ -0,0 +1,59 @@ +<?php + +namespace Mpdf\Tag; + +// TODO: Extend THEAD instead? + +class TFoot extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = 'TFOOT'; // Save current HTML specified optional endtag + $this->cssManager->tbCSSlvl++; + $this->mpdf->tabletfoot = 1; + $this->mpdf->tablethead = 0; + $properties = $this->cssManager->MergeCSS('TABLE', 'TFOOT', $attr); + if (isset($properties['FONT-WEIGHT'])) { + $this->mpdf->tfoot_font_weight = ''; + if (strtoupper($properties['FONT-WEIGHT']) === 'BOLD') { + $this->mpdf->tfoot_font_weight = 'B'; + } + } + + if (isset($properties['FONT-STYLE'])) { + $this->mpdf->tfoot_font_style = ''; + if (strtoupper($properties['FONT-STYLE']) === 'ITALIC') { + $this->mpdf->tfoot_font_style = 'I'; + } + } + if (isset($properties['FONT-VARIANT'])) { + $this->mpdf->tfoot_font_smCaps = ''; + if (strtoupper($properties['FONT-VARIANT']) === 'SMALL-CAPS') { + $this->mpdf->tfoot_font_smCaps = 'S'; + } + } + + if (isset($properties['VERTICAL-ALIGN'])) { + $this->mpdf->tfoot_valign_default = $properties['VERTICAL-ALIGN']; + } + if (isset($properties['TEXT-ALIGN'])) { + $this->mpdf->tfoot_textalign_default = $properties['TEXT-ALIGN']; + } + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = ''; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + $this->mpdf->tabletfoot = 0; + $this->mpdf->ResetStyles(); + $this->mpdf->tfoot_font_weight = ''; + $this->mpdf->tfoot_font_style = ''; + $this->mpdf->tfoot_font_smCaps = ''; + + $this->mpdf->tfoot_valign_default = ''; + $this->mpdf->tfoot_textalign_default = ''; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/THead.php b/src/vendor/mpdf/mpdf/src/Tag/THead.php new file mode 100644 index 000000000..acd8015ae --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/THead.php @@ -0,0 +1,58 @@ +<?php + +namespace Mpdf\Tag; + +class THead extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = 'THEAD'; // Save current HTML specified optional endtag + $this->cssManager->tbCSSlvl++; + $this->mpdf->tablethead = 1; + $this->mpdf->tabletfoot = 0; + $properties = $this->cssManager->MergeCSS('TABLE', 'THEAD', $attr); + if (isset($properties['FONT-WEIGHT'])) { + $this->mpdf->thead_font_weight = ''; + if (strtoupper($properties['FONT-WEIGHT']) === 'BOLD') { + $this->mpdf->thead_font_weight = 'B'; + } + } + + if (isset($properties['FONT-STYLE'])) { + $this->mpdf->thead_font_style = ''; + if (strtoupper($properties['FONT-STYLE']) === 'ITALIC') { + $this->mpdf->thead_font_style = 'I'; + } + } + if (isset($properties['FONT-VARIANT'])) { + $this->mpdf->thead_font_smCaps = ''; + if (strtoupper($properties['FONT-VARIANT']) === 'SMALL-CAPS') { + $this->mpdf->thead_font_smCaps = 'S'; + } + } + + if (isset($properties['VERTICAL-ALIGN'])) { + $this->mpdf->thead_valign_default = $properties['VERTICAL-ALIGN']; + } + if (isset($properties['TEXT-ALIGN'])) { + $this->mpdf->thead_textalign_default = $properties['TEXT-ALIGN']; + } + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->lastoptionaltag = ''; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + $this->mpdf->tablethead = 0; + $this->mpdf->tabletheadjustfinished = true; + $this->mpdf->ResetStyles(); + $this->mpdf->thead_font_weight = ''; + $this->mpdf->thead_font_style = ''; + $this->mpdf->thead_font_smCaps = ''; + + $this->mpdf->thead_valign_default = ''; + $this->mpdf->thead_textalign_default = ''; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Table.php b/src/vendor/mpdf/mpdf/src/Tag/Table.php new file mode 100644 index 000000000..9ed219c60 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Table.php @@ -0,0 +1,1281 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Css\Border; +use Mpdf\Mpdf; + +class Table extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->tdbegin = false; + $this->mpdf->lastoptionaltag = ''; + // Disable vertical justification in columns + if ($this->mpdf->ColActive) { + $this->mpdf->colvAlign = ''; + } // *COLUMNS* + if ($this->mpdf->lastblocklevelchange == 1) { + $blockstate = 1; + } // Top margins/padding only + elseif ($this->mpdf->lastblocklevelchange < 1) { + $blockstate = 0; + } // NO margins/padding + // called from block after new div e.g. <div> ... <table> ... Outputs block top margin/border and padding + if (count($this->mpdf->textbuffer) == 0 && $this->mpdf->lastblocklevelchange == 1 && !$this->mpdf->tableLevel && !$this->mpdf->kwt) { + $this->mpdf->newFlowingBlock($this->mpdf->blk[$this->mpdf->blklvl]['width'], $this->mpdf->lineheight, '', false, 1, true, $this->mpdf->blk[$this->mpdf->blklvl]['direction']); + $this->mpdf->finishFlowingBlock(true); // true = END of flowing block + } elseif (!$this->mpdf->tableLevel && count($this->mpdf->textbuffer)) { + $this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate); + } + + $this->mpdf->textbuffer = []; + $this->mpdf->lastblocklevelchange = -1; + + + + if ($this->mpdf->tableLevel) { // i.e. now a nested table coming... + // Save current level table + $this->mpdf->cell['PARENTCELL'] = $this->mpdf->saveInlineProperties(); + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['baseProperties'] = $this->mpdf->base_table_properties; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cells'] = $this->mpdf->cell; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['currrow'] = $this->mpdf->row; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['currcol'] = $this->mpdf->col; + } + $this->mpdf->tableLevel++; + $this->cssManager->tbCSSlvl++; + + if ($this->mpdf->tableLevel > 1) { // inherit table properties from cell in which nested + //$this->mpdf->base_table_properties['FONT-KERNING'] = ($this->mpdf->textvar & TextVars::FC_KERNING); // mPDF 6 + $this->mpdf->base_table_properties['LETTER-SPACING'] = $this->mpdf->lSpacingCSS; + $this->mpdf->base_table_properties['WORD-SPACING'] = $this->mpdf->wSpacingCSS; + // mPDF 6 + $direction = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['direction']; + $txta = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['a']; + $cellLineHeight = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['cellLineHeight']; + $cellLineStackingStrategy = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['cellLineStackingStrategy']; + $cellLineStackingShift = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['cellLineStackingShift']; + } + + if (isset($this->mpdf->tbctr[$this->mpdf->tableLevel])) { + $this->mpdf->tbctr[$this->mpdf->tableLevel] ++; + } else { + $this->mpdf->tbctr[$this->mpdf->tableLevel] = 1; + } + + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['level'] = $this->mpdf->tableLevel; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['levelid'] = $this->mpdf->tbctr[$this->mpdf->tableLevel]; + + if ($this->mpdf->tableLevel > $this->mpdf->innermostTableLevel) { + $this->mpdf->innermostTableLevel = $this->mpdf->tableLevel; + } + if ($this->mpdf->tableLevel > 1) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nestedpos'] = [ + $this->mpdf->row, + $this->mpdf->col, + $this->mpdf->tbctr[$this->mpdf->tableLevel - 1], + ]; + } + //++++++++++++++++++++++++++++ + + $this->mpdf->cell = []; + $this->mpdf->col = -1; //int + $this->mpdf->row = -1; //int + $table = &$this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]; + + // New table - any level + $table['direction'] = $this->mpdf->directionality; + $table['bgcolor'] = false; + $table['va'] = false; + $table['txta'] = false; + $table['topntail'] = false; + $table['thead-underline'] = false; + $table['border'] = false; + $table['border_details']['R']['w'] = 0; + $table['border_details']['L']['w'] = 0; + $table['border_details']['T']['w'] = 0; + $table['border_details']['B']['w'] = 0; + $table['border_details']['R']['style'] = ''; + $table['border_details']['L']['style'] = ''; + $table['border_details']['T']['style'] = ''; + $table['border_details']['B']['style'] = ''; + $table['max_cell_border_width']['R'] = 0; + $table['max_cell_border_width']['L'] = 0; + $table['max_cell_border_width']['T'] = 0; + $table['max_cell_border_width']['B'] = 0; + $table['padding']['L'] = false; + $table['padding']['R'] = false; + $table['padding']['T'] = false; + $table['padding']['B'] = false; + $table['margin']['L'] = false; + $table['margin']['R'] = false; + $table['margin']['T'] = false; + $table['margin']['B'] = false; + $table['a'] = false; + $table['border_spacing_H'] = false; + $table['border_spacing_V'] = false; + $table['decimal_align'] = false; + $this->mpdf->Reset(); + $this->mpdf->InlineProperties = []; + $this->mpdf->InlineBDF = []; // mPDF 6 + $this->mpdf->InlineBDFctr = 0; // mPDF 6 + $table['nc'] = $table['nr'] = 0; + $this->mpdf->tablethead = 0; + $this->mpdf->tabletfoot = 0; + $this->mpdf->tabletheadjustfinished = false; + + // mPDF 6 + if ($this->mpdf->tableLevel > 1) { // inherit table properties from cell in which nested + $table['direction'] = $direction; + $table['txta'] = $txta; + $table['cellLineHeight'] = $cellLineHeight; + $table['cellLineStackingStrategy'] = $cellLineStackingStrategy; + $table['cellLineStackingShift'] = $cellLineStackingShift; + } + + + $lastbottommargin = 0; + if ($this->mpdf->blockjustfinished && !count($this->mpdf->textbuffer) && $this->mpdf->y != $this->mpdf->tMargin && $this->mpdf->collapseBlockMargins && $this->mpdf->tableLevel == 1) { + $lastbottommargin = $this->mpdf->lastblockbottommargin; + } + $this->mpdf->lastblockbottommargin = 0; + $this->mpdf->blockjustfinished = false; + + if ($this->mpdf->tableLevel == 1) { + $table['headernrows'] = 0; + $table['footernrows'] = 0; + $this->mpdf->base_table_properties = []; + } + + // ADDED CSS FUNCIONS FOR TABLE + if ($this->cssManager->tbCSSlvl == 1) { + $properties = $this->cssManager->MergeCSS('TOPTABLE', 'TABLE', $attr); + } else { + $properties = $this->cssManager->MergeCSS('TABLE', 'TABLE', $attr); + } + + $w = ''; + if (isset($properties['WIDTH'])) { + $w = $properties['WIDTH']; + } elseif (!empty($attr['WIDTH'])) { + $w = $attr['WIDTH']; + } + + if (isset($attr['ALIGN']) && array_key_exists(strtolower($attr['ALIGN']), self::ALIGN)) { + $table['a'] = $this->getAlign($attr['ALIGN']); + } + if (!$table['a']) { + if ($table['direction'] === 'rtl') { + $table['a'] = 'R'; + } else { + $table['a'] = 'L'; + } + } + + if (!empty($properties['DIRECTION'])) { + $table['direction'] = strtolower($properties['DIRECTION']); + } elseif (!empty($attr['DIR'])) { + $table['direction'] = strtolower($attr['DIR']); + } elseif ($this->mpdf->tableLevel == 1) { + $table['direction'] = $this->mpdf->blk[$this->mpdf->blklvl]['direction']; + } + + if (isset($properties['BACKGROUND-COLOR'])) { + if ($table['bgcolor'] === false) { // @todo cleaner initialization + $table['bgcolor'] = []; + } + $table['bgcolor'][-1] = $properties['BACKGROUND-COLOR']; + } elseif (isset($properties['BACKGROUND'])) { + if ($table['bgcolor'] === false) { + $table['bgcolor'] = []; + } + $table['bgcolor'][-1] = $properties['BACKGROUND']; + } elseif (isset($attr['BGCOLOR'])) { + if ($table['bgcolor'] === false) { + $table['bgcolor'] = []; + } + $table['bgcolor'][-1] = $attr['BGCOLOR']; + } + + if (isset($properties['VERTICAL-ALIGN']) && array_key_exists(strtolower($properties['VERTICAL-ALIGN']), self::ALIGN)) { + $table['va'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + if (isset($properties['TEXT-ALIGN']) && array_key_exists(strtolower($properties['TEXT-ALIGN']), self::ALIGN)) { + $table['txta'] = $this->getAlign($properties['TEXT-ALIGN']); + } + + if (!empty($properties['AUTOSIZE']) && $this->mpdf->tableLevel == 1) { + $this->mpdf->shrink_this_table_to_fit = $properties['AUTOSIZE']; + if ($this->mpdf->shrink_this_table_to_fit < 1) { + $this->mpdf->shrink_this_table_to_fit = 0; + } + } + if (!empty($properties['ROTATE']) && $this->mpdf->tableLevel == 1) { + $this->mpdf->table_rotate = $properties['ROTATE']; + } + if (isset($properties['TOPNTAIL'])) { + $table['topntail'] = $properties['TOPNTAIL']; + } + if (isset($properties['THEAD-UNDERLINE'])) { + $table['thead-underline'] = $properties['THEAD-UNDERLINE']; + } + + if (isset($properties['BORDER'])) { + $bord = $this->mpdf->border_details($properties['BORDER']); + if ($bord['s']) { + $table['border'] = Border::ALL; + $table['border_details']['R'] = $bord; + $table['border_details']['L'] = $bord; + $table['border_details']['T'] = $bord; + $table['border_details']['B'] = $bord; + } + } + if (isset($properties['BORDER-RIGHT'])) { + if ($table['direction'] === 'rtl') { // *OTL* + $table['border_details']['R'] = $this->mpdf->border_details($properties['BORDER-LEFT']); // *OTL* + } // *OTL* + else { // *OTL* + $table['border_details']['R'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } // *OTL* + $this->mpdf->setBorder($table['border'], Border::RIGHT, $table['border_details']['R']['s']); + } + if (isset($properties['BORDER-LEFT'])) { + if ($table['direction'] === 'rtl') { // *OTL* + $table['border_details']['L'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); // *OTL* + } // *OTL* + else { // *OTL* + $table['border_details']['L'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } // *OTL* + $this->mpdf->setBorder($table['border'], Border::LEFT, $table['border_details']['L']['s']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $table['border_details']['B'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + $this->mpdf->setBorder($table['border'], Border::BOTTOM, $table['border_details']['B']['s']); + } + if (isset($properties['BORDER-TOP'])) { + $table['border_details']['T'] = $this->mpdf->border_details($properties['BORDER-TOP']); + $this->mpdf->setBorder($table['border'], Border::TOP, $table['border_details']['T']['s']); + } + + $this->mpdf->table_border_css_set = 0; + if ($table['border']) { + $this->mpdf->table_border_css_set = 1; + } + + // mPDF 6 + if (!empty($properties['LANG'])) { + if ($this->mpdf->autoLangToFont && !$this->mpdf->usingCoreFont) { + if ($properties['LANG'] != $this->mpdf->default_lang && $properties['LANG'] !== 'UTF-8') { + list ($coreSuitable, $mpdf_pdf_unifont) = $this->languageToFont->getLanguageOptions($properties['LANG'], $this->mpdf->useAdobeCJK); + if ($mpdf_pdf_unifont) { + $properties['FONT-FAMILY'] = $mpdf_pdf_unifont; + } + } + } + $this->mpdf->currentLang = $properties['LANG']; + } + + + if (isset($properties['FONT-FAMILY'])) { + $this->mpdf->default_font = $properties['FONT-FAMILY']; + $this->mpdf->SetFont($this->mpdf->default_font, '', 0, false); + } + $this->mpdf->base_table_properties['FONT-FAMILY'] = $this->mpdf->FontFamily; + + if (isset($properties['FONT-SIZE'])) { + if ($this->mpdf->tableLevel > 1) { + $tableFontSize = $this->sizeConverter->convert($this->mpdf->base_table_properties['FONT-SIZE']); + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $tableFontSize); + } else { + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $this->mpdf->default_font_size / Mpdf::SCALE); + } + if ($mmsize) { + $this->mpdf->default_font_size = $mmsize * Mpdf::SCALE; + $this->mpdf->SetFontSize($this->mpdf->default_font_size, false); + } + } + $this->mpdf->base_table_properties['FONT-SIZE'] = $this->mpdf->FontSize . 'mm'; + + if (isset($properties['FONT-WEIGHT'])) { + if (strtoupper($properties['FONT-WEIGHT']) === 'BOLD') { + $this->mpdf->base_table_properties['FONT-WEIGHT'] = 'BOLD'; + } + } + if (isset($properties['FONT-STYLE'])) { + if (strtoupper($properties['FONT-STYLE']) === 'ITALIC') { + $this->mpdf->base_table_properties['FONT-STYLE'] = 'ITALIC'; + } + } + if (isset($properties['COLOR'])) { + $this->mpdf->base_table_properties['COLOR'] = $properties['COLOR']; + } + if (isset($properties['FONT-KERNING'])) { + $this->mpdf->base_table_properties['FONT-KERNING'] = $properties['FONT-KERNING']; + } + if (isset($properties['LETTER-SPACING'])) { + $this->mpdf->base_table_properties['LETTER-SPACING'] = $properties['LETTER-SPACING']; + } + if (isset($properties['WORD-SPACING'])) { + $this->mpdf->base_table_properties['WORD-SPACING'] = $properties['WORD-SPACING']; + } + // mPDF 6 + if (isset($properties['HYPHENS'])) { + $this->mpdf->base_table_properties['HYPHENS'] = $properties['HYPHENS']; + } + if (!empty($properties['LINE-HEIGHT'])) { + $table['cellLineHeight'] = $this->mpdf->fixLineheight($properties['LINE-HEIGHT']); + } elseif ($this->mpdf->tableLevel == 1) { + $table['cellLineHeight'] = $this->mpdf->blk[$this->mpdf->blklvl]['line_height']; + } + + if (!empty($properties['LINE-STACKING-STRATEGY'])) { + $table['cellLineStackingStrategy'] = strtolower($properties['LINE-STACKING-STRATEGY']); + } elseif ($this->mpdf->tableLevel == 1 && isset($this->mpdf->blk[$this->mpdf->blklvl]['line_stacking_strategy'])) { + $table['cellLineStackingStrategy'] = $this->mpdf->blk[$this->mpdf->blklvl]['line_stacking_strategy']; + } else { + $table['cellLineStackingStrategy'] = 'inline-line-height'; + } + + if (!empty($properties['LINE-STACKING-SHIFT'])) { + $table['cellLineStackingShift'] = strtolower($properties['LINE-STACKING-SHIFT']); + } elseif ($this->mpdf->tableLevel == 1 && isset($this->mpdf->blk[$this->mpdf->blklvl]['line_stacking_shift'])) { + $table['cellLineStackingShift'] = $this->mpdf->blk[$this->mpdf->blklvl]['line_stacking_shift']; + } else { + $table['cellLineStackingShift'] = 'consider-shifts'; + } + + if (isset($properties['PADDING-LEFT'])) { + $table['padding']['L'] = $this->sizeConverter->convert($properties['PADDING-LEFT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-RIGHT'])) { + $table['padding']['R'] = $this->sizeConverter->convert($properties['PADDING-RIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-TOP'])) { + $table['padding']['T'] = $this->sizeConverter->convert($properties['PADDING-TOP'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-BOTTOM'])) { + $table['padding']['B'] = $this->sizeConverter->convert($properties['PADDING-BOTTOM'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['MARGIN-TOP'])) { + if ($lastbottommargin) { + $tmp = $this->sizeConverter->convert($properties['MARGIN-TOP'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + if ($tmp > $lastbottommargin) { + $properties['MARGIN-TOP'] = (int) $properties['MARGIN-TOP'] - $lastbottommargin; + } else { + $properties['MARGIN-TOP'] = 0; + } + } + $table['margin']['T'] = $this->sizeConverter->convert($properties['MARGIN-TOP'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['MARGIN-BOTTOM'])) { + $table['margin']['B'] = $this->sizeConverter->convert($properties['MARGIN-BOTTOM'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['MARGIN-LEFT'])) { + $table['margin']['L'] = $this->sizeConverter->convert($properties['MARGIN-LEFT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['MARGIN-RIGHT'])) { + $table['margin']['R'] = $this->sizeConverter->convert($properties['MARGIN-RIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['MARGIN-LEFT'], $properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-LEFT']) === 'auto' && strtolower($properties['MARGIN-RIGHT']) === 'auto') { + $table['a'] = 'C'; + } elseif (isset($properties['MARGIN-LEFT']) && strtolower($properties['MARGIN-LEFT']) === 'auto') { + $table['a'] = 'R'; + } elseif (isset($properties['MARGIN-RIGHT']) && strtolower($properties['MARGIN-RIGHT']) === 'auto') { + $table['a'] = 'L'; + } + + if (isset($properties['BORDER-COLLAPSE']) && strtoupper($properties['BORDER-COLLAPSE']) === 'SEPARATE') { + $table['borders_separate'] = true; + } else { + $table['borders_separate'] = false; + } + + // mPDF 5.7.3 + + if (isset($properties['BORDER-SPACING-H'])) { + $table['border_spacing_H'] = $this->sizeConverter->convert($properties['BORDER-SPACING-H'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['BORDER-SPACING-V'])) { + $table['border_spacing_V'] = $this->sizeConverter->convert($properties['BORDER-SPACING-V'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + // mPDF 5.7.3 + if (!$table['borders_separate']) { + $table['border_spacing_H'] = $table['border_spacing_V'] = 0; + } + + if (isset($properties['EMPTY-CELLS'])) { + $table['empty_cells'] = strtolower($properties['EMPTY-CELLS']); // 'hide' or 'show' + } else { + $table['empty_cells'] = ''; + } + + if (isset($properties['PAGE-BREAK-INSIDE']) && strtoupper($properties['PAGE-BREAK-INSIDE']) === 'AVOID' && $this->mpdf->tableLevel == 1 && !$this->mpdf->writingHTMLfooter) { + $this->mpdf->table_keep_together = true; + } elseif ($this->mpdf->tableLevel == 1) { + $this->mpdf->table_keep_together = false; + } + if (isset($properties['PAGE-BREAK-AFTER']) && $this->mpdf->tableLevel == 1) { + $table['page_break_after'] = strtoupper($properties['PAGE-BREAK-AFTER']); + } + + /* -- BACKGROUNDS -- */ + if (isset($properties['BACKGROUND-GRADIENT']) && !$this->mpdf->kwt && !$this->mpdf->ColActive) { + $table['gradient'] = $properties['BACKGROUND-GRADIENT']; + } + + if (!empty($properties['BACKGROUND-IMAGE']) && !$this->mpdf->kwt && !$this->mpdf->ColActive) { + $ret = $this->mpdf->SetBackground($properties, $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + if ($ret) { + $table['background-image'] = $ret; + } + } + /* -- END BACKGROUNDS -- */ + + if (isset($properties['OVERFLOW'])) { + $table['overflow'] = strtolower($properties['OVERFLOW']); // 'hidden' 'wrap' or 'visible' or 'auto' + if (($this->mpdf->ColActive || $this->mpdf->tableLevel > 1) && $table['overflow'] === 'visible') { + unset($table['overflow']); + } + } + + if (isset($attr['CELLPADDING'])) { + $table['cell_padding'] = $attr['CELLPADDING']; + } else { + $table['cell_padding'] = false; + } + + if (isset($attr['BORDER']) && $attr['BORDER'] == '1') { + $this->mpdf->table_border_attr_set = 1; + $bord = $this->mpdf->border_details('#000000 1px solid'); + if ($bord['s']) { + $table['border'] = Border::ALL; + $table['border_details']['R'] = $bord; + $table['border_details']['L'] = $bord; + $table['border_details']['T'] = $bord; + $table['border_details']['B'] = $bord; + } + } else { + $this->mpdf->table_border_attr_set = 0; + } + + if ($w) { + $maxwidth = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; + if ($table['borders_separate']) { + $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['border_details']['L']['w'] / 2 + $table['border_details']['R']['w'] / 2; + } else { + $tblblw = $table['margin']['L'] + $table['margin']['R'] + $table['max_cell_border_width']['L'] / 2 + $table['max_cell_border_width']['R'] / 2; + } + if (strpos($w, '%') && $this->mpdf->tableLevel == 1 && !$this->mpdf->ignore_table_percents) { + // % needs to be of inner box without table margins etc. + $maxwidth -= $tblblw; + $wmm = $this->sizeConverter->convert($w, $maxwidth, $this->mpdf->FontSize, false); + $table['w'] = $wmm + $tblblw; + } + if (strpos($w, '%') && $this->mpdf->tableLevel > 1 && !$this->mpdf->ignore_table_percents && $this->mpdf->keep_table_proportions) { + $table['wpercent'] = (int) $w; // makes 80% -> 80 + } + if (!strpos($w, '%') && !$this->mpdf->ignore_table_widths) { + $wmm = $this->sizeConverter->convert($w, $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + $table['w'] = $wmm + $tblblw; + } + if (!$this->mpdf->keep_table_proportions) { + if (isset($table['w']) && $table['w'] > $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']) { + $table['w'] = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; + } + } + } + + if (isset($attr['AUTOSIZE']) && $this->mpdf->tableLevel == 1) { + $this->mpdf->shrink_this_table_to_fit = $attr['AUTOSIZE']; + if ($this->mpdf->shrink_this_table_to_fit < 1) { + $this->mpdf->shrink_this_table_to_fit = 1; + } + } + if (isset($attr['ROTATE']) && $this->mpdf->tableLevel == 1) { + $this->mpdf->table_rotate = $attr['ROTATE']; + } + + //++++++++++++++++++++++++++++ + if ($this->mpdf->table_rotate) { + $this->mpdf->tbrot_Links = []; + $this->mpdf->tbrot_Annots = []; + $this->mpdf->tbrotForms = []; + $this->mpdf->tbrot_BMoutlines = []; + $this->mpdf->tbrot_toc = []; + } + + if ($this->mpdf->kwt) { + if ($this->mpdf->table_rotate) { + $this->mpdf->table_keep_together = true; + } + $this->mpdf->kwt = false; + $this->mpdf->kwt_saved = true; + } + + //++++++++++++++++++++++++++++ + $this->mpdf->plainCell_properties = []; + unset($table); + } + + public function close(&$ahtml, &$ihtml) + { + + $this->mpdf->lastoptionaltag = ''; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + $this->mpdf->ignorefollowingspaces = true; //Eliminate exceeding left-side spaces + // mPDF 5.7.3 + // In case a colspan (on a row after first row) exceeded number of columns in table + for ($k = 0; $k < $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nr']; $k++) { + for ($l = 0; $l < $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc']; $l++) { + if (!isset($this->mpdf->cell[$k][$l])) { + for ($n = $l - 1; $n >= 0; $n--) { + if (isset($this->mpdf->cell[$k][$n]) && $this->mpdf->cell[$k][$n] != 0) { + break; + } + } + $this->mpdf->cell[$k][$l] = [ + 'a' => 'C', + 'va' => 'M', + 'R' => false, + 'nowrap' => false, + 'bgcolor' => false, + 'padding' => ['L' => false, 'R' => false, 'T' => false, 'B' => false], + 'gradient' => false, + 's' => 0, + 'maxs' => 0, + 'textbuffer' => [], + 'dfs' => $this->mpdf->FontSize, + ]; + + if (!$this->mpdf->simpleTables) { + $this->mpdf->cell[$k][$l]['border'] = 0; + $this->mpdf->cell[$k][$l]['border_details']['R'] = ['s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0]; + $this->mpdf->cell[$k][$l]['border_details']['L'] = ['s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0]; + $this->mpdf->cell[$k][$l]['border_details']['T'] = ['s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0]; + $this->mpdf->cell[$k][$l]['border_details']['B'] = ['s' => 0, 'w' => 0, 'c' => false, 'style' => 'none', 'dom' => 0]; + $this->mpdf->cell[$k][$l]['border_details']['mbw'] = ['BL' => 0, 'BR' => 0, 'RT' => 0, 'RB' => 0, 'TL' => 0, 'TR' => 0, 'LT' => 0, 'LB' => 0]; + if ($this->mpdf->packTableData) { + $this->mpdf->cell[$k][$l]['borderbin'] = $this->mpdf->_packCellBorder($this->mpdf->cell[$k][$l]); + unset($this->mpdf->cell[$k][$l]['border'], $this->mpdf->cell[$k][$l]['border_details']); + } + } + } + } + } + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cells'] = $this->mpdf->cell; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['wc'] = array_pad( + [], + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'], + ['miw' => 0, 'maw' => 0] + ); + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['hr'] = array_pad( + [], + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nr'], + 0 + ); + + // Move table footer <tfoot> row to end of table + if (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot']) + && count($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'])) { + $tfrows = []; + foreach ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'] as $r => $val) { + if ($val) { + $tfrows[] = $r; + } + } + $temp = []; + $temptf = []; + foreach ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cells'] as $k => $row) { + if (in_array($k, $tfrows)) { + $temptf[] = $row; + } else { + $temp[] = $row; + } + } + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'] = []; + for ($i = count($temp); $i < (count($temp) + count($temptf)); $i++) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'][$i] = true; + } + // Update nestedpos row references + if (isset($this->mpdf->table[$this->mpdf->tableLevel + 1]) && count($this->mpdf->table[$this->mpdf->tableLevel + 1])) { + foreach ($this->mpdf->table[$this->mpdf->tableLevel + 1] as $nid => $nested) { + $this->mpdf->table[$this->mpdf->tableLevel + 1][$nid]['nestedpos'][0] -= count($temptf); + } + } + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cells'] = array_merge($temp, $temptf); + + // Update other arays set on row number + // [trbackground-images] [trgradients] + $temptrbgi = []; + $temptrbgg = []; + $temptrbgc = []; + if (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][-1])) { + $temptrbgc[-1] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][-1]; + } + for ($k = 0; $k < $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nr']; $k++) { + if (!in_array($k, $tfrows)) { + $temptrbgi[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'][$k] + : null; + $temptrbgg[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'][$k] + : null; + $temptrbgc[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$k] + : null; + } + } + for ($k = 0; $k < $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nr']; $k++) { + if (in_array($k, $tfrows)) { + $temptrbgi[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'][$k] + : null; + $temptrbgg[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'][$k] + : null; + $temptrbgc[] = isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$k]) + ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$k] + : null; + } + } + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'] = $temptrbgi; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'] = $temptrbgg; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] = $temptrbgc; + // Should Update all other arays set on row number, but cell properties have been set so not needed + // [bgcolor] [trborder-left] [trborder-right] [trborder-top] [trborder-bottom] + } + + if ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['direction'] === 'rtl') { + $this->mpdf->_reverseTableDir($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]); + } + + // Fix Borders ********************************************* + $this->mpdf->_fixTableBorders($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]); + + if ($this->mpdf->ColActive) { + $this->mpdf->table_rotate = 0; + } // *COLUMNS* + if ($this->mpdf->table_rotate <> 0) { + $this->mpdf->tablebuffer = ''; + // Max width for rotated table + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 1); + $this->mpdf->tbrot_maxh = $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']; // Max width for rotated table + $this->mpdf->tbrot_align = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['a']; + } + $this->mpdf->shrin_k = 1; + + if ($this->mpdf->shrink_tables_to_fit < 1) { + $this->mpdf->shrink_tables_to_fit = 1; + } + if (!$this->mpdf->shrink_this_table_to_fit) { + $this->mpdf->shrink_this_table_to_fit = $this->mpdf->shrink_tables_to_fit; + } + + if ($this->mpdf->tableLevel > 1) { + // deal with nested table + + $this->mpdf->_tableColumnWidth($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]], true); + + $tmiw = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['miw']; + $tmaw = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['maw']; + $tl = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['tl']; + + // Go down to lower table level + $this->mpdf->tableLevel--; + + // Reset lower level table + $this->mpdf->base_table_properties = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['baseProperties']; + // mPDF 5.7.3 + $this->mpdf->default_font = $this->mpdf->base_table_properties['FONT-FAMILY']; + $this->mpdf->SetFont($this->mpdf->default_font, '', 0, false); + $this->mpdf->default_font_size = $this->sizeConverter->convert($this->mpdf->base_table_properties['FONT-SIZE']) * Mpdf::SCALE; + $this->mpdf->SetFontSize($this->mpdf->default_font_size, false); + + $this->mpdf->cell = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['cells']; + if (isset($this->mpdf->cell['PARENTCELL'])) { + if ($this->mpdf->cell['PARENTCELL']) { + $this->mpdf->restoreInlineProperties($this->mpdf->cell['PARENTCELL']); + } + unset($this->mpdf->cell['PARENTCELL']); + } + $this->mpdf->row = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['currrow']; + $this->mpdf->col = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['currcol']; + $objattr = []; + $objattr['type'] = 'nestedtable'; + $objattr['nestedcontent'] = $this->mpdf->tbctr[$this->mpdf->tableLevel + 1]; + $objattr['table'] = $this->mpdf->tbctr[$this->mpdf->tableLevel]; + $objattr['row'] = $this->mpdf->row; + $objattr['col'] = $this->mpdf->col; + $objattr['level'] = $this->mpdf->tableLevel; + $e = Mpdf::OBJECT_IDENTIFIER . "type=nestedtable,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + $this->mpdf->_saveCellTextBuffer($e); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $tl; + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; // reset + if ((isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmaw']) && $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmaw'] < $tmaw) + || !isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmaw'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmaw'] = $tmaw; + } + if ((isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmiw']) && $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmiw'] < $tmiw) + || !isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmiw'])) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['nestedmiw'] = $tmiw; + } + $this->mpdf->tdbegin = true; + $this->mpdf->nestedtablejustfinished = true; + $this->mpdf->ignorefollowingspaces = true; + return; + } + $this->mpdf->cMarginL = 0; + $this->mpdf->cMarginR = 0; + $this->mpdf->cMarginT = 0; + $this->mpdf->cMarginB = 0; + $this->mpdf->cellPaddingL = 0; + $this->mpdf->cellPaddingR = 0; + $this->mpdf->cellPaddingT = 0; + $this->mpdf->cellPaddingB = 0; + + if (isset($this->mpdf->table[1][1]['overflow']) && $this->mpdf->table[1][1]['overflow'] === 'visible') { + if ($this->mpdf->kwt || $this->mpdf->table_rotate || $this->mpdf->table_keep_together || $this->mpdf->ColActive) { + $this->mpdf->kwt = false; + $this->mpdf->table_rotate = 0; + $this->mpdf->table_keep_together = false; + //throw new \Mpdf\MpdfException("mPDF Warning: You cannot use CSS overflow:visible together with any of these functions: + // 'Keep-with-table', rotated tables, page-break-inside:avoid, or columns"); + } + $this->mpdf->_tableColumnWidth($this->mpdf->table[1][1], true); + $this->mpdf->_tableWidth($this->mpdf->table[1][1]); + } else { + if (!$this->mpdf->kwt_saved) { + $this->mpdf->kwt_height = 0; + } + + list($check, $tablemiw) = $this->mpdf->_tableColumnWidth($this->mpdf->table[1][1], true); + $save_table = $this->mpdf->table; + $reset_to_minimum_width = false; + $added_page = false; + + if ($check > 1) { + if ($check > $this->mpdf->shrink_this_table_to_fit && $this->mpdf->table_rotate) { + if ($this->mpdf->y != $this->mpdf->tMargin) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $this->mpdf->kwt_moved = true; + } + $added_page = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + //$check = $tablemiw/$this->mpdf->tbrot_maxw; // undo any shrink + $check = 1; // undo any shrink + } + $reset_to_minimum_width = true; + } + + if ($reset_to_minimum_width) { + $this->mpdf->shrin_k = $check; + + $this->mpdf->default_font_size /= $this->mpdf->shrin_k; + $this->mpdf->SetFontSize($this->mpdf->default_font_size, false); + + $this->mpdf->shrinkTable($this->mpdf->table[1][1], $this->mpdf->shrin_k); + + $this->mpdf->_tableColumnWidth($this->mpdf->table[1][1]); // repeat + // Starting at $this->mpdf->innermostTableLevel + // Shrink table values - and redo columnWidth + for ($lvl = 2; $lvl <= $this->mpdf->innermostTableLevel; $lvl++) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + $this->mpdf->shrinkTable($this->mpdf->table[$lvl][$nid], $this->mpdf->shrin_k); + $this->mpdf->_tableColumnWidth($this->mpdf->table[$lvl][$nid]); + } + } + } + + // Set table cell widths for top level table + // Use $shrin_k to resize but don't change again + $this->mpdf->SetLineHeight('', $this->mpdf->table[1][1]['cellLineHeight']); + + // Top level table + $this->mpdf->_tableWidth($this->mpdf->table[1][1]); + } + + // Now work through any nested tables setting child table[w'] = parent cell['w'] + // Now do nested tables _tableWidth + for ($lvl = 2; $lvl <= $this->mpdf->innermostTableLevel; $lvl++) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + // HERE set child table width = cell width + + list($parentrow, $parentcol, $parentnid) = $this->mpdf->table[$lvl][$nid]['nestedpos']; + + $c = & $this->mpdf->table[$lvl - 1][$parentnid]['cells'][$parentrow][$parentcol]; + + if (isset($c['colspan']) && $c['colspan'] > 1) { + $parentwidth = 0; + for ($cs = 0; $cs < $c['colspan']; $cs++) { + $parentwidth += $this->mpdf->table[$lvl - 1][$parentnid]['wc'][$parentcol + $cs]; + } + } else { + $parentwidth = $this->mpdf->table[$lvl - 1][$parentnid]['wc'][$parentcol]; + } + + //$parentwidth -= ALLOW FOR PADDING ETC. in parent cell + if (!$this->mpdf->simpleTables) { + if ($this->mpdf->packTableData) { + list($bt, $br, $bb, $bl) = $this->mpdf->_getBorderWidths($c['borderbin']); + } else { + $br = $c['border_details']['R']['w']; + $bl = $c['border_details']['L']['w']; + } + if ($this->mpdf->table[$lvl - 1][$parentnid]['borders_separate']) { + $parentwidth -= $br + $bl + $c['padding']['L'] + $c['padding']['R'] + $this->mpdf->table[$lvl - 1][$parentnid]['border_spacing_H']; + } else { + $parentwidth -= $br / 2 + $bl / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } elseif ($this->mpdf->simpleTables) { + if ($this->mpdf->table[$lvl - 1][$parentnid]['borders_separate']) { + $parentwidth -= $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['L']['w'] + + $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['R']['w'] + $c['padding']['L'] + + $c['padding']['R'] + $this->mpdf->table[$lvl - 1][$parentnid]['border_spacing_H']; + } else { + $parentwidth -= $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['L']['w'] / 2 + + $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['R']['w'] / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } + if (!empty($this->mpdf->table[$lvl][$nid]['wpercent']) && $lvl > 1) { + $this->mpdf->table[$lvl][$nid]['w'] = $parentwidth; + } elseif ($parentwidth > $this->mpdf->table[$lvl][$nid]['maw']) { + $this->mpdf->table[$lvl][$nid]['w'] = $this->mpdf->table[$lvl][$nid]['maw']; + } else { + $this->mpdf->table[$lvl][$nid]['w'] = $parentwidth; + } + unset($c); + $this->mpdf->_tableWidth($this->mpdf->table[$lvl][$nid]); + } + } + + // Starting at $this->mpdf->innermostTableLevel + // Cascade back up nested tables: setting heights back up the tree + for ($lvl = $this->mpdf->innermostTableLevel; $lvl > 0; $lvl--) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + list($tableheight, $maxrowheight, $fullpage, $remainingpage, $maxfirstrowheight) = $this->mpdf->_tableHeight($this->mpdf->table[$lvl][$nid]); + } + } + + if ($this->mpdf->table[1][1]['overflow'] === 'visible') { + if ($maxrowheight > $fullpage) { + throw new \Mpdf\MpdfException('mPDF Warning: A Table row is greater than available height. You cannot use CSS overflow:visible'); + } + if ($maxfirstrowheight > $remainingpage) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + $r = 0; + $c = 0; + $p = 0; + $y = 0; + $finished = false; + while (!$finished) { + list($finished, $r, $c, $p, $y, $y0) = $this->mpdf->_tableWrite($this->mpdf->table[1][1], true, $r, $c, $p, $y); + if (!$finished) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + // If printed something on first spread, set same y + if ($r == 0 && $y0 > -1) { + $this->mpdf->y = $y0; + } + } + } + } else { + $recalculate = 1; + $forcerecalc = false; + // RESIZING ALGORITHM + if ($maxrowheight > $fullpage) { + $recalculate = $this->tbsqrt($maxrowheight / $fullpage, 1); + $forcerecalc = true; + } elseif ($this->mpdf->table_rotate) { // NB $remainingpage == $fullpage == the width of the page + if ($tableheight > $remainingpage) { + // If can fit on remainder of page whilst respecting autsize value.. + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1); + } elseif (!$added_page) { + if ($this->mpdf->y != $this->mpdf->tMargin) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $this->mpdf->kwt_moved = true; + } + $added_page = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + // 0.001 to force it to recalculate + $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; // undo any shrink + } + } else { + $recalculate = 1; + } + } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) { + if ($tableheight > $fullpage) { + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $fullpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $fullpage, 1); + } elseif ($this->mpdf->tableMinSizePriority) { + $this->mpdf->table_keep_together = false; + $recalculate = 1.001; + } else { + if ($this->mpdf->y != $this->mpdf->tMargin) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $this->mpdf->kwt_moved = true; + } + $added_page = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + $recalculate = $this->tbsqrt($tableheight / $fullpage, 1); + } + } elseif ($tableheight > $remainingpage) { + // If can fit on remainder of page whilst respecting autsize value.. + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1); + } else { + if ($this->mpdf->y != $this->mpdf->tMargin) { + // mPDF 6 + if ($this->mpdf->AcceptPageBreak()) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } elseif ($this->mpdf->ColActive && $tableheight > (($this->mpdf->h - $this->mpdf->bMargin) - $this->mpdf->y0)) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + $this->mpdf->kwt_moved = true; + } + $added_page = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + $recalculate = 1.001; + } + } else { + $recalculate = 1; + } + } else { + $recalculate = 1; + } + + if ($recalculate > $this->mpdf->shrink_this_table_to_fit && !$forcerecalc) { + $recalculate = $this->mpdf->shrink_this_table_to_fit; + } + + $iteration = 1; + + // RECALCULATE + while ($recalculate <> 1) { + $this->mpdf->shrin_k1 = $recalculate; + $this->mpdf->shrin_k *= $recalculate; + $this->mpdf->default_font_size /= $this->mpdf->shrin_k1; + $this->mpdf->SetFontSize($this->mpdf->default_font_size, false); + $this->mpdf->SetLineHeight('', $this->mpdf->table[1][1]['cellLineHeight']); + $this->mpdf->table = $save_table; + if ($this->mpdf->shrin_k <> 1) { + $this->mpdf->shrinkTable($this->mpdf->table[1][1], $this->mpdf->shrin_k); + } + $this->mpdf->_tableColumnWidth($this->mpdf->table[1][1]); // repeat + // Starting at $this->mpdf->innermostTableLevel + // Shrink table values - and redo columnWidth + for ($lvl = 2; $lvl <= $this->mpdf->innermostTableLevel; $lvl++) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + if ($this->mpdf->shrin_k <> 1) { + $this->mpdf->shrinkTable($this->mpdf->table[$lvl][$nid], $this->mpdf->shrin_k); + } + $this->mpdf->_tableColumnWidth($this->mpdf->table[$lvl][$nid]); + } + } + // Set table cell widths for top level table + // Top level table + $this->mpdf->_tableWidth($this->mpdf->table[1][1]); + + // Now work through any nested tables setting child table[w'] = parent cell['w'] + // Now do nested tables _tableWidth + for ($lvl = 2; $lvl <= $this->mpdf->innermostTableLevel; $lvl++) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + // HERE set child table width = cell width + + list($parentrow, $parentcol, $parentnid) = $this->mpdf->table[$lvl][$nid]['nestedpos']; + $c = & $this->mpdf->table[$lvl - 1][$parentnid]['cells'][$parentrow][$parentcol]; + + if (isset($c['colspan']) && $c['colspan'] > 1) { + $parentwidth = 0; + for ($cs = 0; $cs < $c['colspan']; $cs++) { + $parentwidth += $this->mpdf->table[$lvl - 1][$parentnid]['wc'][$parentcol + $cs]; + } + } else { + $parentwidth = $this->mpdf->table[$lvl - 1][$parentnid]['wc'][$parentcol]; + } + + //$parentwidth -= ALLOW FOR PADDING ETC.in parent cell + if (!$this->mpdf->simpleTables) { + if ($this->mpdf->packTableData) { + list($bt, $br, $bb, $bl) = $this->mpdf->_getBorderWidths($c['borderbin']); + } else { + $br = $c['border_details']['R']['w']; + $bl = $c['border_details']['L']['w']; + } + if ($this->mpdf->table[$lvl - 1][$parentnid]['borders_separate']) { + $parentwidth -= $br + $bl + $c['padding']['L'] + $c['padding']['R'] + $this->mpdf->table[$lvl - 1][$parentnid]['border_spacing_H']; + } else { + $parentwidth -= $br / 2 + $bl / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } elseif ($this->mpdf->simpleTables) { + if ($this->mpdf->table[$lvl - 1][$parentnid]['borders_separate']) { + $parentwidth -= $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['L']['w'] + + $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['R']['w'] + $c['padding']['L'] + $c['padding']['R'] + + $this->mpdf->table[$lvl - 1][$parentnid]['border_spacing_H']; + } else { + $parentwidth -= ($this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['L']['w'] + + $this->mpdf->table[$lvl - 1][$parentnid]['simple']['border_details']['R']['w']) / 2 + $c['padding']['L'] + $c['padding']['R']; + } + } + if (!empty($this->mpdf->table[$lvl][$nid]['wpercent']) && $lvl > 1) { + $this->mpdf->table[$lvl][$nid]['w'] = $parentwidth; + } elseif ($parentwidth > $this->mpdf->table[$lvl][$nid]['maw']) { + $this->mpdf->table[$lvl][$nid]['w'] = $this->mpdf->table[$lvl][$nid]['maw']; + } else { + $this->mpdf->table[$lvl][$nid]['w'] = $parentwidth; + } + unset($c); + $this->mpdf->_tableWidth($this->mpdf->table[$lvl][$nid]); + } + } + + // Starting at $this->mpdf->innermostTableLevel + // Cascade back up nested tables: setting heights back up the tree + for ($lvl = $this->mpdf->innermostTableLevel; $lvl > 0; $lvl--) { + for ($nid = 1; $nid <= $this->mpdf->tbctr[$lvl]; $nid++) { + list($tableheight, $maxrowheight, $fullpage, $remainingpage, $maxfirstrowheight) = $this->mpdf->_tableHeight($this->mpdf->table[$lvl][$nid]); + } + } + + // RESIZING ALGORITHM + + if ($maxrowheight > $fullpage) { + $recalculate = $this->tbsqrt($maxrowheight / $fullpage, $iteration); + $iteration++; + } elseif ($this->mpdf->table_rotate && $tableheight > $remainingpage && !$added_page) { + // If can fit on remainder of page whilst respecting autosize value.. + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); + $iteration++; + } else { + if (!$added_page) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $added_page = true; + $this->mpdf->kwt_moved = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + } + // 0.001 to force it to recalculate + $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; // undo any shrink + } + } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) { + if ($tableheight > $fullpage) { + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); + $iteration++; + } elseif ($this->mpdf->tableMinSizePriority) { + $this->mpdf->table_keep_together = false; + $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; + } else { + if (!$added_page && $this->mpdf->y != $this->mpdf->tMargin) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $added_page = true; + $this->mpdf->kwt_moved = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + } + $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); + $iteration++; + } + } elseif ($tableheight > $remainingpage) { + // If can fit on remainder of page whilst respecting autosize value.. + if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) { + $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration); + $iteration++; + } else { + if (!$added_page) { + // mPDF 6 + if ($this->mpdf->AcceptPageBreak()) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } elseif ($this->mpdf->ColActive && $tableheight > (($this->mpdf->h - $this->mpdf->bMargin) - $this->mpdf->y0)) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + $added_page = true; + $this->mpdf->kwt_moved = true; + $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height; + } + + //$recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++; + $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; // undo any shrink + } + } else { + $recalculate = 1; + } + } else { + $recalculate = 1; + } + } + + if ($maxfirstrowheight > $remainingpage && !$added_page && !$this->mpdf->table_rotate && !$this->mpdf->ColActive + && !$this->mpdf->table_keep_together && !$this->mpdf->writingHTMLheader && !$this->mpdf->writingHTMLfooter) { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + $this->mpdf->kwt_moved = true; + } + + // keep-with-table: if page has advanced, print out buffer now, else done in fn. _Tablewrite() + if ($this->mpdf->kwt_saved && $this->mpdf->kwt_moved) { + $this->mpdf->printkwtbuffer(); + $this->mpdf->kwt_moved = false; + $this->mpdf->kwt_saved = false; + } + + // Recursively writes all tables starting at top level + $this->mpdf->_tableWrite($this->mpdf->table[1][1]); + + if ($this->mpdf->table_rotate && $this->mpdf->tablebuffer) { + $this->mpdf->PageBreakTrigger = $this->mpdf->h - $this->mpdf->bMargin; + $save_tr = $this->mpdf->table_rotate; + $save_y = $this->mpdf->y; + $this->mpdf->table_rotate = 0; + $this->mpdf->y = $this->mpdf->tbrot_y0; + $h = $this->mpdf->tbrot_w; + $this->mpdf->DivLn($h, $this->mpdf->blklvl); + + $this->mpdf->table_rotate = $save_tr; + $this->mpdf->y = $save_y; + + $this->mpdf->printtablebuffer(); + } + $this->mpdf->table_rotate = 0; + } + + + $this->mpdf->x = $this->mpdf->lMargin + $this->mpdf->blk[$this->mpdf->blklvl]['outer_left_margin']; + + $this->mpdf->maxPosR = max($this->mpdf->maxPosR, $this->mpdf->x + $this->mpdf->table[1][1]['w']); + + $this->mpdf->blockjustfinished = true; + $this->mpdf->lastblockbottommargin = $this->mpdf->table[1][1]['margin']['B']; + //Reset values + + $page_break_after = ''; + if (isset($this->mpdf->table[1][1]['page_break_after'])) { + $page_break_after = $this->mpdf->table[1][1]['page_break_after']; + } + + // Keep-with-table + $this->mpdf->kwt = false; + $this->mpdf->kwt_y0 = 0; + $this->mpdf->kwt_x0 = 0; + $this->mpdf->kwt_height = 0; + $this->mpdf->kwt_buffer = []; + $this->mpdf->kwt_Links = []; + $this->mpdf->kwt_Annots = []; + $this->mpdf->kwt_moved = false; + $this->mpdf->kwt_saved = false; + + $this->mpdf->kwt_Reference = []; + $this->mpdf->kwt_BMoutlines = []; + $this->mpdf->kwt_toc = []; + + $this->mpdf->shrin_k = 1; + $this->mpdf->shrink_this_table_to_fit = 0; + + $this->mpdf->table = []; //array + $this->mpdf->tableLevel = 0; + $this->mpdf->tbctr = []; + $this->mpdf->innermostTableLevel = 0; + $this->cssManager->tbCSSlvl = 0; + $this->cssManager->tablecascadeCSS = []; + + $this->mpdf->cell = []; //array + + $this->mpdf->col = -1; //int + $this->mpdf->row = -1; //int + + $this->mpdf->Reset(); + + $this->mpdf->cellPaddingL = 0; + $this->mpdf->cellPaddingT = 0; + $this->mpdf->cellPaddingR = 0; + $this->mpdf->cellPaddingB = 0; + $this->mpdf->cMarginL = 0; + $this->mpdf->cMarginT = 0; + $this->mpdf->cMarginR = 0; + $this->mpdf->cMarginB = 0; + $this->mpdf->default_font_size = $this->mpdf->original_default_font_size; + $this->mpdf->default_font = $this->mpdf->original_default_font; + $this->mpdf->SetFontSize($this->mpdf->default_font_size, false); + $this->mpdf->SetFont($this->mpdf->default_font, '', 0, false); + $this->mpdf->SetLineHeight(); + + if (isset($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties'])) { + $this->mpdf->restoreInlineProperties($this->mpdf->blk[$this->mpdf->blklvl]['InlineProperties']); + } + + if ($page_break_after) { + $save_blklvl = $this->mpdf->blklvl; + $save_blk = $this->mpdf->blk; + $save_silp = $this->mpdf->saveInlineProperties(); + $save_ilp = $this->mpdf->InlineProperties; + $save_bflp = $this->mpdf->InlineBDF; + $save_bflpc = $this->mpdf->InlineBDFctr; // mPDF 6 + // mPDF 6 pagebreaktype + $startpage = $this->mpdf->page; + $pagebreaktype = $this->mpdf->defaultPagebreakType; + if ($this->mpdf->ColActive) { + $pagebreaktype = 'cloneall'; + } + + // mPDF 6 pagebreaktype + $this->mpdf->_preForcedPagebreak($pagebreaktype); + + if ($page_break_after === 'RIGHT') { + $this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-ODD'); + } elseif ($page_break_after === 'LEFT') { + $this->mpdf->AddPage($this->mpdf->CurOrientation, 'NEXT-EVEN'); + } else { + $this->mpdf->AddPage($this->mpdf->CurOrientation); + } + + // mPDF 6 pagebreaktype + $this->mpdf->_postForcedPagebreak($pagebreaktype, $startpage, $save_blk, $save_blklvl); + + $this->mpdf->InlineProperties = $save_ilp; + $this->mpdf->InlineBDF = $save_bflp; + $this->mpdf->InlineBDFctr = $save_bflpc; // mPDF 6 + $this->mpdf->restoreInlineProperties($save_silp); + } + } + + /** + * This function determines the shrink factor when resizing tables + * val is the table_height / page_height_available + * returns a scaling factor used as $shrin_k to resize the table + * Overcompensating will be quicker but may unnecessarily shrink table too much + * Undercompensating means it will reiterate more times (taking more processing time) + */ + private function tbsqrt($val, $iteration = 3) + { + // Alters number of iterations until it returns $val itself - Must be > 2 + $k = 4; + + // Probably best guess and most accurate + if ($iteration === 1) { + return sqrt($val); + } + + // Faster than using sqrt (because it won't undercompensate), and gives reasonable results + // return 1 + (($val - 1) / 2); + $x = 2 - (($iteration - 2) / ($k - 2)); + + if ($x === 0) { + $ret = $val + 0.00001; + } elseif ($x < 0) { + $ret = 1 + ( pow(2, ($iteration - 2 - $k)) / 1000 ); + } else { + $ret = 1 + (($val - 1) / $x); + } + + return $ret; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Tag.php b/src/vendor/mpdf/mpdf/src/Tag/Tag.php new file mode 100644 index 000000000..094b2a46f --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Tag.php @@ -0,0 +1,127 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Strict; + +use Mpdf\Cache; +use Mpdf\Color\ColorConverter; +use Mpdf\CssManager; +use Mpdf\Form; +use Mpdf\Image\ImageProcessor; +use Mpdf\Language\LanguageToFontInterface; +use Mpdf\Mpdf; +use Mpdf\Otl; +use Mpdf\SizeConverter; +use Mpdf\TableOfContents; + +abstract class Tag +{ + + use Strict; + + /** + * @var \Mpdf\Mpdf + */ + protected $mpdf; + + /** + * @var \Mpdf\Cache + */ + protected $cache; + + /** + * @var \Mpdf\CssManager + */ + protected $cssManager; + + /** + * @var \Mpdf\Form + */ + protected $form; + + /** + * @var \Mpdf\Otl + */ + protected $otl; + + /** + * @var \Mpdf\TableOfContents + */ + protected $tableOfContents; + + /** + * @var \Mpdf\SizeConverter + */ + protected $sizeConverter; + + /** + * @var \Mpdf\Color\ColorConverter + */ + protected $colorConverter; + + /** + * @var \Mpdf\Image\ImageProcessor + */ + protected $imageProcessor; + + /** + * @var \Mpdf\Language\LanguageToFontInterface + */ + protected $languageToFont; + + const ALIGN = [ + 'left' => 'L', + 'center' => 'C', + 'right' => 'R', + 'top' => 'T', + 'text-top' => 'TT', + 'middle' => 'M', + 'baseline' => 'BS', + 'bottom' => 'B', + 'text-bottom' => 'TB', + 'justify' => 'J' + ]; + + public function __construct( + Mpdf $mpdf, + Cache $cache, + CssManager $cssManager, + Form $form, + Otl $otl, + TableOfContents $tableOfContents, + SizeConverter $sizeConverter, + ColorConverter $colorConverter, + ImageProcessor $imageProcessor, + LanguageToFontInterface $languageToFont + ) { + + $this->mpdf = $mpdf; + $this->cache = $cache; + $this->cssManager = $cssManager; + $this->form = $form; + $this->otl = $otl; + $this->tableOfContents = $tableOfContents; + $this->sizeConverter = $sizeConverter; + $this->colorConverter = $colorConverter; + $this->imageProcessor = $imageProcessor; + $this->languageToFont = $languageToFont; + } + + public function getTagName() + { + $tag = get_class($this); + return strtoupper(str_replace('Mpdf\Tag\\', '', $tag)); + } + + protected function getAlign($property) + { + $property = strtolower($property); + return array_key_exists($property, self::ALIGN) ? self::ALIGN[$property] : ''; + } + + abstract public function open($attr, &$ahtml, &$ihtml); + + abstract public function close(&$ahtml, &$ihtml); + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Td.php b/src/vendor/mpdf/mpdf/src/Tag/Td.php new file mode 100644 index 000000000..5f82fab7b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Td.php @@ -0,0 +1,486 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Css\Border; +use Mpdf\Css\TextVars; +use Mpdf\Utils\UtfString; + +class Td extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $tag = $this->getTagName(); + + $this->mpdf->ignorefollowingspaces = true; + $this->mpdf->lastoptionaltag = $tag; // Save current HTML specified optional endtag + + $this->cssManager->tbCSSlvl++; + + $this->mpdf->InlineProperties = []; + $this->mpdf->InlineBDF = []; // mPDF 6 + $this->mpdf->InlineBDFctr = 0; // mPDF 6 + $this->mpdf->tdbegin = true; + $this->mpdf->col++; + + while (isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col])) { + $this->mpdf->col++; + } + + // Update number column + if ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] < $this->mpdf->col + 1) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] = $this->mpdf->col + 1; + } + + $table = &$this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]; + + $c = ['a' => false, + 'R' => false, + 'nowrap' => false, + 'bgcolor' => false, + 'padding' => ['L' => false, + 'R' => false, + 'T' => false, + 'B' => false + ] + ]; + + if ($this->mpdf->simpleTables && $this->mpdf->row == 0 && $this->mpdf->col == 0) { + $table['simple']['border'] = false; + $table['simple']['border_details']['R']['w'] = 0; + $table['simple']['border_details']['L']['w'] = 0; + $table['simple']['border_details']['T']['w'] = 0; + $table['simple']['border_details']['B']['w'] = 0; + $table['simple']['border_details']['R']['style'] = ''; + $table['simple']['border_details']['L']['style'] = ''; + $table['simple']['border_details']['T']['style'] = ''; + $table['simple']['border_details']['B']['style'] = ''; + } elseif (!$this->mpdf->simpleTables) { + + $c['border'] = false; + $c['border_details']['R']['w'] = 0; + $c['border_details']['L']['w'] = 0; + $c['border_details']['T']['w'] = 0; + $c['border_details']['B']['w'] = 0; + $c['border_details']['mbw']['BL'] = 0; + $c['border_details']['mbw']['BR'] = 0; + $c['border_details']['mbw']['RT'] = 0; + $c['border_details']['mbw']['RB'] = 0; + $c['border_details']['mbw']['TL'] = 0; + $c['border_details']['mbw']['TR'] = 0; + $c['border_details']['mbw']['LT'] = 0; + $c['border_details']['mbw']['LB'] = 0; + $c['border_details']['R']['style'] = ''; + $c['border_details']['L']['style'] = ''; + $c['border_details']['T']['style'] = ''; + $c['border_details']['B']['style'] = ''; + $c['border_details']['R']['s'] = 0; + $c['border_details']['L']['s'] = 0; + $c['border_details']['T']['s'] = 0; + $c['border_details']['B']['s'] = 0; + $c['border_details']['R']['c'] = $this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings); + $c['border_details']['L']['c'] = $this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings); + $c['border_details']['T']['c'] = $this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings); + $c['border_details']['B']['c'] = $this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings); + $c['border_details']['R']['dom'] = 0; + $c['border_details']['L']['dom'] = 0; + $c['border_details']['T']['dom'] = 0; + $c['border_details']['B']['dom'] = 0; + $c['border_details']['cellposdom'] = 0; + } + + if ($table['va']) { + $c['va'] = $table['va']; + } + + if ($table['txta']) { + $c['a'] = $table['txta']; + } + + if ($this->mpdf->table_border_attr_set && $table['border_details']) { + + if (!$this->mpdf->simpleTables) { + $c['border_details']['R'] = $table['border_details']['R']; + $c['border_details']['L'] = $table['border_details']['L']; + $c['border_details']['T'] = $table['border_details']['T']; + $c['border_details']['B'] = $table['border_details']['B']; + $c['border'] = $table['border']; + $c['border_details']['L']['dom'] = 1; + $c['border_details']['R']['dom'] = 1; + $c['border_details']['T']['dom'] = 1; + $c['border_details']['B']['dom'] = 1; + } elseif ($this->mpdf->simpleTables && $this->mpdf->row == 0 && $this->mpdf->col == 0) { + $table['simple']['border_details']['R'] = $table['border_details']['R']; + $table['simple']['border_details']['L'] = $table['border_details']['L']; + $table['simple']['border_details']['T'] = $table['border_details']['T']; + $table['simple']['border_details']['B'] = $table['border_details']['B']; + $table['simple']['border'] = $table['border']; + } + } + + // INHERITED THEAD CSS Properties + if ($this->mpdf->tablethead) { + + if ($this->mpdf->thead_valign_default) { + $c['va'] = $this->getAlign($this->mpdf->thead_valign_default); + } + + if ($this->mpdf->thead_textalign_default) { + $c['a'] = $this->getAlign($this->mpdf->thead_textalign_default); + } + + if ($this->mpdf->thead_font_weight === 'B') { + $this->mpdf->SetStyle('B', true); + } + + if ($this->mpdf->thead_font_style === 'I') { + $this->mpdf->SetStyle('I', true); + } + + if ($this->mpdf->thead_font_smCaps === 'S') { + $this->mpdf->textvar |= TextVars::FC_SMALLCAPS; + } // mPDF 5.7.1 + } + + // INHERITED TFOOT CSS Properties + if ($this->mpdf->tabletfoot) { + if ($this->mpdf->tfoot_valign_default) { + $c['va'] = $this->getAlign($this->mpdf->tfoot_valign_default); + } + if ($this->mpdf->tfoot_textalign_default) { + $c['a'] = $this->getAlign($this->mpdf->tfoot_textalign_default); + } + if ($this->mpdf->tfoot_font_weight === 'B') { + $this->mpdf->SetStyle('B', true); + } + if ($this->mpdf->tfoot_font_style === 'I') { + $this->mpdf->SetStyle('I', true); + } + if ($this->mpdf->tfoot_font_style === 'S') { + $this->mpdf->textvar |= TextVars::FC_SMALLCAPS; + } // mPDF 5.7.1 + } + + + if ($this->mpdf->trow_text_rotate) { + $c['R'] = $this->mpdf->trow_text_rotate; + } + + $this->mpdf->cell_border_dominance_L = 0; + $this->mpdf->cell_border_dominance_R = 0; + $this->mpdf->cell_border_dominance_T = 0; + $this->mpdf->cell_border_dominance_B = 0; + + $properties = $this->cssManager->MergeCSS('TABLE', $tag, $attr); + + $properties = $this->cssManager->array_merge_recursive_unique($this->mpdf->base_table_properties, $properties); + + $this->mpdf->Reset(); // mPDF 6 ????????????????????? + + $this->mpdf->setCSS($properties, 'TABLECELL', $tag); + + $c['dfs'] = $this->mpdf->FontSize; // Default Font size + + + if (isset($properties['BACKGROUND-COLOR'])) { + $c['bgcolor'] = $properties['BACKGROUND-COLOR']; + } elseif (isset($properties['BACKGROUND'])) { + $c['bgcolor'] = $properties['BACKGROUND']; + } elseif (isset($attr['BGCOLOR'])) { + $c['bgcolor'] = $attr['BGCOLOR']; + } + + + + /* -- BACKGROUNDS -- */ + if (isset($properties['BACKGROUND-GRADIENT'])) { + $c['gradient'] = $properties['BACKGROUND-GRADIENT']; + } else { + $c['gradient'] = false; + } + + if (!empty($properties['BACKGROUND-IMAGE']) && !$this->mpdf->keep_block_together) { + $ret = $this->mpdf->SetBackground($properties, $this->mpdf->blk[$this->mpdf->blklvl]['inner_width']); + if ($ret) { + $c['background-image'] = $ret; + } + } + /* -- END BACKGROUNDS -- */ + if (isset($properties['VERTICAL-ALIGN'])) { + $c['va'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } elseif (isset($attr['VALIGN'])) { + $c['va'] = $this->getAlign($attr['VALIGN']); + } + + + if (!empty($properties['TEXT-ALIGN'])) { + if (0 === strpos($properties['TEXT-ALIGN'], 'D')) { + $c['a'] = $properties['TEXT-ALIGN']; + } else { + $c['a'] = $this->getAlign($properties['TEXT-ALIGN']); + } + } + if (!empty($attr['ALIGN'])) { + if (strtolower($attr['ALIGN']) === 'char') { + if (!empty($attr['CHAR'])) { + $char = html_entity_decode($attr['CHAR']); + $char = UtfString::strcode2utf($char); + $d = array_search($char, $this->mpdf->decimal_align); + if ($d !== false) { + $c['a'] = $d . 'R'; + } + } else { + $c['a'] = 'DPR'; + } + } else { + $c['a'] = $this->getAlign($attr['ALIGN']); + } + } + + // mPDF 6 + $c['direction'] = $table['direction']; + if (isset($attr['DIR']) && $attr['DIR'] != '') { + $c['direction'] = strtolower($attr['DIR']); + } + if (isset($properties['DIRECTION'])) { + $c['direction'] = strtolower($properties['DIRECTION']); + } + + if (!$c['a']) { + if (isset($c['direction']) && $c['direction'] === 'rtl') { + $c['a'] = 'R'; + } else { + $c['a'] = 'L'; + } + } + + $c['cellLineHeight'] = $table['cellLineHeight']; + if (isset($properties['LINE-HEIGHT'])) { + $c['cellLineHeight'] = $this->mpdf->fixLineheight($properties['LINE-HEIGHT']); + } + + $c['cellLineStackingStrategy'] = $table['cellLineStackingStrategy']; + if (isset($properties['LINE-STACKING-STRATEGY'])) { + $c['cellLineStackingStrategy'] = strtolower($properties['LINE-STACKING-STRATEGY']); + } + + $c['cellLineStackingShift'] = $table['cellLineStackingShift']; + if (isset($properties['LINE-STACKING-SHIFT'])) { + $c['cellLineStackingShift'] = strtolower($properties['LINE-STACKING-SHIFT']); + } + + if (isset($properties['TEXT-ROTATE']) && ($properties['TEXT-ROTATE'] || $properties['TEXT-ROTATE'] === '0')) { + $c['R'] = $properties['TEXT-ROTATE']; + } + if (isset($properties['BORDER'])) { + $bord = $this->mpdf->border_details($properties['BORDER']); + if ($bord['s']) { + if (!$this->mpdf->simpleTables) { + $c['border'] = Border::ALL; + $c['border_details']['R'] = $bord; + $c['border_details']['L'] = $bord; + $c['border_details']['T'] = $bord; + $c['border_details']['B'] = $bord; + $c['border_details']['L']['dom'] = $this->mpdf->cell_border_dominance_L; + $c['border_details']['R']['dom'] = $this->mpdf->cell_border_dominance_R; + $c['border_details']['T']['dom'] = $this->mpdf->cell_border_dominance_T; + $c['border_details']['B']['dom'] = $this->mpdf->cell_border_dominance_B; + } elseif ($this->mpdf->simpleTables && $this->mpdf->row == 0 && $this->mpdf->col == 0) { + $table['simple']['border'] = Border::ALL; + $table['simple']['border_details']['R'] = $bord; + $table['simple']['border_details']['L'] = $bord; + $table['simple']['border_details']['T'] = $bord; + $table['simple']['border_details']['B'] = $bord; + } + } + } + if (!$this->mpdf->simpleTables) { + if (!empty($properties['BORDER-RIGHT'])) { + $c['border_details']['R'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + $this->mpdf->setBorder($c['border'], Border::RIGHT, $c['border_details']['R']['s']); + $c['border_details']['R']['dom'] = $this->mpdf->cell_border_dominance_R; + } + if (!empty($properties['BORDER-LEFT'])) { + $c['border_details']['L'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + $this->mpdf->setBorder($c['border'], Border::LEFT, $c['border_details']['L']['s']); + $c['border_details']['L']['dom'] = $this->mpdf->cell_border_dominance_L; + } + if (!empty($properties['BORDER-BOTTOM'])) { + $c['border_details']['B'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + $this->mpdf->setBorder($c['border'], Border::BOTTOM, $c['border_details']['B']['s']); + $c['border_details']['B']['dom'] = $this->mpdf->cell_border_dominance_B; + } + if (!empty($properties['BORDER-TOP'])) { + $c['border_details']['T'] = $this->mpdf->border_details($properties['BORDER-TOP']); + $this->mpdf->setBorder($c['border'], Border::TOP, $c['border_details']['T']['s']); + $c['border_details']['T']['dom'] = $this->mpdf->cell_border_dominance_T; + } + } elseif ($this->mpdf->simpleTables && $this->mpdf->row == 0 && $this->mpdf->col == 0) { + if (!empty($properties['BORDER-LEFT'])) { + $bord = $this->mpdf->border_details($properties['BORDER-LEFT']); + if ($bord['s']) { + $table['simple']['border'] = Border::ALL; + } else { + $table['simple']['border'] = 0; + } + $table['simple']['border_details']['R'] = $bord; + $table['simple']['border_details']['L'] = $bord; + $table['simple']['border_details']['T'] = $bord; + $table['simple']['border_details']['B'] = $bord; + } + } + + if ($this->mpdf->simpleTables && $this->mpdf->row == 0 && $this->mpdf->col == 0 && !$table['borders_separate'] && $table['simple']['border']) { + $table['border_details'] = $table['simple']['border_details']; + $table['border'] = $table['simple']['border']; + } + + // Border set on TR (if collapsed only) + if (!$table['borders_separate'] && !$this->mpdf->simpleTables && isset($table['trborder-left'][$this->mpdf->row])) { + if ($this->mpdf->col == 0) { + $left = $this->mpdf->border_details($table['trborder-left'][$this->mpdf->row]); + $c['border_details']['L'] = $left; + $this->mpdf->setBorder($c['border'], Border::LEFT, $c['border_details']['L']['s']); + } + $c['border_details']['B'] = $this->mpdf->border_details($table['trborder-bottom'][$this->mpdf->row]); + $this->mpdf->setBorder($c['border'], Border::BOTTOM, $c['border_details']['B']['s']); + $c['border_details']['T'] = $this->mpdf->border_details($table['trborder-top'][$this->mpdf->row]); + $this->mpdf->setBorder($c['border'], Border::TOP, $c['border_details']['T']['s']); + } + + if ($this->mpdf->packTableData && !$this->mpdf->simpleTables) { + $c['borderbin'] = $this->mpdf->_packCellBorder($c); + unset($c['border'], $c['border_details']); + } + + if (isset($properties['PADDING-LEFT'])) { + $c['padding']['L'] = $this->sizeConverter->convert($properties['PADDING-LEFT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-RIGHT'])) { + $c['padding']['R'] = $this->sizeConverter->convert($properties['PADDING-RIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-BOTTOM'])) { + $c['padding']['B'] = $this->sizeConverter->convert($properties['PADDING-BOTTOM'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + if (isset($properties['PADDING-TOP'])) { + $c['padding']['T'] = $this->sizeConverter->convert($properties['PADDING-TOP'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + $w = ''; + if (isset($properties['WIDTH'])) { + $w = $properties['WIDTH']; + } elseif (isset($attr['WIDTH'])) { + $w = $attr['WIDTH']; + } + if ($w) { + if (strpos($w, '%') && !$this->mpdf->ignore_table_percents) { + $c['wpercent'] = (float) $w; + } // makes 80% -> 80 + elseif (!strpos($w, '%') && !$this->mpdf->ignore_table_widths) { + $c['w'] = $this->sizeConverter->convert($w, $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + } + + if (isset($properties['HEIGHT']) && !strpos($properties['HEIGHT'], '%')) { + $c['h'] = $this->sizeConverter->convert($properties['HEIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } elseif (isset($attr['HEIGHT']) && !strpos($attr['HEIGHT'], '%')) { + $c['h'] = $this->sizeConverter->convert($attr['HEIGHT'], $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], $this->mpdf->FontSize, false); + } + + if (isset($properties['WHITE-SPACE'])) { + if (strtoupper($properties['WHITE-SPACE']) === 'NOWRAP') { + $c['nowrap'] = 1; + } + } + + if (isset($attr['TEXT-ROTATE'])) { + $c['R'] = $attr['TEXT-ROTATE']; + } + if (!empty($attr['NOWRAP'])) { + $c['nowrap'] = 1; + } + + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col] = $c; + unset($c); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; + + $cs = $rs = 1; + if (isset($attr['COLSPAN']) && preg_match('/^\d+$/', $attr['COLSPAN']) && $attr['COLSPAN'] > 1) { + $cs = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['colspan'] = $attr['COLSPAN']; + } + + if ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] < $this->mpdf->col + $cs) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] = $this->mpdf->col + $cs; + } // following code moved outside if... + + for ($l = $this->mpdf->col; $l < $this->mpdf->col + $cs; $l++) { + if ($l - $this->mpdf->col) { + $this->mpdf->cell[$this->mpdf->row][$l] = 0; + } + } + + if (isset($attr['ROWSPAN']) && preg_match('/^\d+$/', $attr['ROWSPAN']) && $attr['ROWSPAN'] > 1) { + $rs = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['rowspan'] = $attr['ROWSPAN']; + } + + for ($k = $this->mpdf->row; $k < $this->mpdf->row + $rs; $k++) { + for ($l = $this->mpdf->col; $l < $this->mpdf->col + $cs; $l++) { + if ($k - $this->mpdf->row || $l - $this->mpdf->col) { + $this->mpdf->cell[$k][$l] = 0; + } + } + } + unset($table); + } + + public function close(&$ahtml, &$ihtml) + { + if ($this->mpdf->tableLevel) { + $this->mpdf->lastoptionaltag = 'TR'; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + if (!$this->mpdf->tdbegin) { + return; + } + $this->mpdf->tdbegin = false; + // Added for correct calculation of cell column width - otherwise misses the last line if not end </p> etc. + if (!isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'])) { + if (!is_array($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col])) { + throw new \Mpdf\MpdfException('You may have an error in your HTML code e.g. </td></td>'); + } + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } elseif ($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] < $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['maxs'] = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s']; + } + + // Remove last <br> if at end of cell + $ntb = 0; + if (isset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'])) { + $ntb = count($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer']); + } + if ($ntb > 1 && $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][$ntb - 1][0] === "\n") { + unset($this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][$ntb - 1]); + } + + if ($this->mpdf->tablethead) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead'][$this->mpdf->row] = true; + if ($this->mpdf->tableLevel == 1) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['headernrows'] + = max($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['headernrows'], $this->mpdf->row + 1); + } + } + if ($this->mpdf->tabletfoot) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'][$this->mpdf->row] = true; + if ($this->mpdf->tableLevel == 1) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['footernrows'] + = max( + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['footernrows'], + $this->mpdf->row + 1 - $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['headernrows'] + ); + } + } + $this->mpdf->Reset(); + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TextArea.php b/src/vendor/mpdf/mpdf/src/Tag/TextArea.php new file mode 100644 index 000000000..46539d8b5 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TextArea.php @@ -0,0 +1,166 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class TextArea extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + if (isset($attr['DISABLED'])) { + $objattr['disabled'] = true; + } + if (isset($attr['READONLY'])) { + $objattr['readonly'] = true; + } + if (isset($attr['REQUIRED'])) { + $objattr['required'] = true; + } + if (isset($attr['SPELLCHECK']) && strtolower($attr['SPELLCHECK']) === 'true') { + $objattr['spellcheck'] = true; + } + if (isset($attr['TITLE'])) { + $objattr['title'] = $attr['TITLE']; + if ($this->mpdf->onlyCoreFonts) { + $objattr['title'] = mb_convert_encoding($objattr['title'], $this->mpdf->mb_enc, 'UTF-8'); + } + } + if ($this->mpdf->useActiveForms) { + if (isset($attr['NAME'])) { + $objattr['fieldname'] = $attr['NAME']; + } + $this->form->form_element_spacing['textarea']['outer']['v'] = 0; + $this->form->form_element_spacing['textarea']['inner']['v'] = 0; + if (isset($attr['ONCALCULATE'])) { + $objattr['onCalculate'] = $attr['ONCALCULATE']; + } elseif (isset($attr['ONCHANGE'])) { + $objattr['onCalculate'] = $attr['ONCHANGE']; + } + if (isset($attr['ONVALIDATE'])) { + $objattr['onValidate'] = $attr['ONVALIDATE']; + } + if (isset($attr['ONKEYSTROKE'])) { + $objattr['onKeystroke'] = $attr['ONKEYSTROKE']; + } + if (isset($attr['ONFORMAT'])) { + $objattr['onFormat'] = $attr['ONFORMAT']; + } + } + $this->mpdf->InlineProperties['TEXTAREA'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('', 'TEXTAREA', $attr); + if (isset($properties['FONT-FAMILY'])) { + $this->mpdf->SetFont($properties['FONT-FAMILY'], '', 0, false); + } + if (isset($properties['FONT-SIZE']) && $properties['FONT-SIZE'] !== 'auto') { + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $this->mpdf->default_font_size / Mpdf::SCALE); + $this->mpdf->SetFontSize($mmsize * Mpdf::SCALE, false); + } + if (isset($properties['COLOR'])) { + $objattr['color'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } + $objattr['fontfamily'] = $this->mpdf->FontFamily; + $objattr['fontsize'] = $this->mpdf->FontSizePt; + if ($this->mpdf->useActiveForms) { + if (isset($properties['TEXT-ALIGN'])) { + $objattr['text_align'] = $this->getAlign($properties['TEXT-ALIGN']); + } elseif (isset($attr['ALIGN'])) { + $objattr['text_align'] = $this->getAlign($attr['ALIGN']); + } + if (isset($properties['OVERFLOW']) && strtolower($properties['OVERFLOW']) === 'hidden') { + $objattr['donotscroll'] = true; + } + if (isset($properties['BORDER-TOP-COLOR'])) { + $objattr['border-col'] = $this->colorConverter->convert($properties['BORDER-TOP-COLOR'], $this->mpdf->PDFAXwarnings); + } + if (isset($properties['BACKGROUND-COLOR'])) { + $objattr['background-col'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings); + } + } + $this->mpdf->SetLineHeight('', $this->form->textarea_lineheight); + + $w = 0; + $h = 0; + if (isset($properties['WIDTH'])) { + $w = $this->sizeConverter->convert( + $properties['WIDTH'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['HEIGHT'])) { + $h = $this->sizeConverter->convert( + $properties['HEIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['VERTICAL-ALIGN'])) { + $objattr['vertical-align'] = $this->getAlign($properties['VERTICAL-ALIGN']); + } + + $colsize = 20; //HTML default value + $rowsize = 2; //HTML default value + if (isset($attr['COLS'])) { + $colsize = (int) $attr['COLS']; + } + if (isset($attr['ROWS'])) { + $rowsize = (int) $attr['ROWS']; + } + + $charsize = $this->mpdf->GetCharWidth('w', false); + if ($w) { + $colsize = round(($w - ($this->form->form_element_spacing['textarea']['outer']['h'] * 2) + - ($this->form->form_element_spacing['textarea']['inner']['h'] * 2)) / $charsize); + } + if ($h) { + $rowsize = round(($h - ($this->form->form_element_spacing['textarea']['outer']['v'] * 2) + - ($this->form->form_element_spacing['textarea']['inner']['v'] * 2)) / $this->mpdf->lineheight); + } + + $objattr['type'] = 'textarea'; + $objattr['width'] = ($colsize * $charsize) + ($this->form->form_element_spacing['textarea']['outer']['h'] * 2) + + ($this->form->form_element_spacing['textarea']['inner']['h'] * 2); + + $objattr['height'] = ($rowsize * $this->mpdf->lineheight) + + ($this->form->form_element_spacing['textarea']['outer']['v'] * 2) + + ($this->form->form_element_spacing['textarea']['inner']['v'] * 2); + + $objattr['rows'] = $rowsize; + $objattr['cols'] = $colsize; + + if ($properties['FONT-SIZE'] === 'auto' && $this->mpdf->useActiveForms) { + $objattr['use_auto_fontsize'] = true; + } + + $this->mpdf->specialcontent = serialize($objattr); + + if ($this->mpdf->tableLevel) { // *TABLES* + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; // *TABLES* + } // *TABLES* + } + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->ignorefollowingspaces = false; + $this->mpdf->specialcontent = ''; + if ($this->mpdf->InlineProperties['TEXTAREA']) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['TEXTAREA']); + } + unset($this->mpdf->InlineProperties['TEXTAREA']); + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TextCircle.php b/src/vendor/mpdf/mpdf/src/Tag/TextCircle.php new file mode 100644 index 000000000..7d321441b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TextCircle.php @@ -0,0 +1,250 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; +use Mpdf\Utils\UtfString; + +class TextCircle extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $objattr = []; + $objattr['margin_top'] = 0; + $objattr['margin_bottom'] = 0; + $objattr['margin_left'] = 0; + $objattr['margin_right'] = 0; + $objattr['padding_top'] = 0; + $objattr['padding_bottom'] = 0; + $objattr['padding_left'] = 0; + $objattr['padding_right'] = 0; + $objattr['width'] = 0; + $objattr['height'] = 0; + $objattr['border_top']['w'] = 0; + $objattr['border_bottom']['w'] = 0; + $objattr['border_left']['w'] = 0; + $objattr['border_right']['w'] = 0; + $objattr['top-text'] = ''; + $objattr['bottom-text'] = ''; + $objattr['r'] = 20; // radius (default value here for safety) + $objattr['space-width'] = 120; + $objattr['char-width'] = 100; + + $this->mpdf->InlineProperties['TEXTCIRCLE'] = $this->mpdf->saveInlineProperties(); + $properties = $this->cssManager->MergeCSS('INLINE', 'TEXTCIRCLE', $attr); + + if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') { + return; + } + if (isset($attr['R'])) { + $objattr['r'] = $this->sizeConverter->convert( + $attr['R'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($attr['TOP-TEXT'])) { + $objattr['top-text'] = UtfString::strcode2utf($attr['TOP-TEXT']); + $objattr['top-text'] = $this->mpdf->lesser_entity_decode($objattr['top-text']); + if ($this->mpdf->onlyCoreFonts) { + $objattr['top-text'] = mb_convert_encoding($objattr['top-text'], $this->mpdf->mb_enc, 'UTF-8'); + } + } + if (isset($attr['BOTTOM-TEXT'])) { + $objattr['bottom-text'] = UtfString::strcode2utf($attr['BOTTOM-TEXT']); + $objattr['bottom-text'] = $this->mpdf->lesser_entity_decode($objattr['bottom-text']); + if ($this->mpdf->onlyCoreFonts) { + $objattr['bottom-text'] = mb_convert_encoding($objattr['bottom-text'], $this->mpdf->mb_enc, 'UTF-8'); + } + } + if (!empty($attr['SPACE-WIDTH'])) { + $objattr['space-width'] = $attr['SPACE-WIDTH']; + } + if (!empty($attr['CHAR-WIDTH'])) { + $objattr['char-width'] = $attr['CHAR-WIDTH']; + } + + // VISIBILITY + $objattr['visibility'] = 'visible'; + if (isset($properties['VISIBILITY'])) { + $v = strtolower($properties['VISIBILITY']); + if (($v === 'hidden' || $v === 'printonly' || $v === 'screenonly') && $this->mpdf->visibility === 'visible') { + $objattr['visibility'] = $v; + } + } + if (isset($properties['FONT-SIZE'])) { + if (strtolower($properties['FONT-SIZE']) === 'auto') { + if ($objattr['top-text'] && $objattr['bottom-text']) { + $objattr['fontsize'] = -2; + } else { + $objattr['fontsize'] = -1; + } + } else { + $mmsize = $this->sizeConverter->convert($properties['FONT-SIZE'], $this->mpdf->default_font_size / Mpdf::SCALE); + $this->mpdf->SetFontSize($mmsize * Mpdf::SCALE, false); + $objattr['fontsize'] = $this->mpdf->FontSizePt; + } + } + if (isset($attr['DIVIDER'])) { + $objattr['divider'] = UtfString::strcode2utf($attr['DIVIDER']); + $objattr['divider'] = $this->mpdf->lesser_entity_decode($objattr['divider']); + if ($this->mpdf->onlyCoreFonts) { + $objattr['divider'] = mb_convert_encoding($objattr['divider'], $this->mpdf->mb_enc, 'UTF-8'); + } + } + + if (isset($properties['COLOR'])) { + $objattr['color'] = $this->colorConverter->convert($properties['COLOR'], $this->mpdf->PDFAXwarnings); + } + + $objattr['fontstyle'] = ''; + if (isset($properties['FONT-WEIGHT'])) { + if (strtoupper($properties['FONT-WEIGHT']) === 'BOLD') { + $objattr['fontstyle'] .= 'B'; + } + } + if (isset($properties['FONT-STYLE'])) { + if (strtoupper($properties['FONT-STYLE']) === 'ITALIC') { + $objattr['fontstyle'] .= 'I'; + } + } + + if (isset($properties['FONT-FAMILY'])) { + $this->mpdf->SetFont($properties['FONT-FAMILY'], $this->mpdf->FontStyle, 0, false); + } + $objattr['fontfamily'] = $this->mpdf->FontFamily; + + // VSPACE and HSPACE converted to margins in MergeCSS + if (isset($properties['MARGIN-TOP'])) { + $objattr['margin_top'] = $this->sizeConverter->convert( + $properties['MARGIN-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-BOTTOM'])) { + $objattr['margin_bottom'] = $this->sizeConverter->convert( + $properties['MARGIN-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-LEFT'])) { + $objattr['margin_left'] = $this->sizeConverter->convert( + $properties['MARGIN-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['MARGIN-RIGHT'])) { + $objattr['margin_right'] = $this->sizeConverter->convert( + $properties['MARGIN-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['PADDING-TOP'])) { + $objattr['padding_top'] = $this->sizeConverter->convert( + $properties['PADDING-TOP'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-BOTTOM'])) { + $objattr['padding_bottom'] = $this->sizeConverter->convert( + $properties['PADDING-BOTTOM'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-LEFT'])) { + $objattr['padding_left'] = $this->sizeConverter->convert( + $properties['PADDING-LEFT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + if (isset($properties['PADDING-RIGHT'])) { + $objattr['padding_right'] = $this->sizeConverter->convert( + $properties['PADDING-RIGHT'], + $this->mpdf->blk[$this->mpdf->blklvl]['inner_width'], + $this->mpdf->FontSize, + false + ); + } + + if (isset($properties['BORDER-TOP'])) { + $objattr['border_top'] = $this->mpdf->border_details($properties['BORDER-TOP']); + } + if (isset($properties['BORDER-BOTTOM'])) { + $objattr['border_bottom'] = $this->mpdf->border_details($properties['BORDER-BOTTOM']); + } + if (isset($properties['BORDER-LEFT'])) { + $objattr['border_left'] = $this->mpdf->border_details($properties['BORDER-LEFT']); + } + if (isset($properties['BORDER-RIGHT'])) { + $objattr['border_right'] = $this->mpdf->border_details($properties['BORDER-RIGHT']); + } + + if (isset($properties['OPACITY']) && $properties['OPACITY'] > 0 && $properties['OPACITY'] <= 1) { + $objattr['opacity'] = $properties['OPACITY']; + } + if (isset($properties['BACKGROUND-COLOR']) && $properties['BACKGROUND-COLOR'] != '') { + $objattr['bgcolor'] = $this->colorConverter->convert($properties['BACKGROUND-COLOR'], $this->mpdf->PDFAXwarnings); + } else { + $objattr['bgcolor'] = false; + } + if ($this->mpdf->HREF) { + if (strpos($this->mpdf->HREF, '.') === false && strpos($this->mpdf->HREF, '@') !== 0) { + $href = $this->mpdf->HREF; + while (array_key_exists($href, $this->mpdf->internallink)) { + $href = '#' . $href; + } + $this->mpdf->internallink[$href] = $this->mpdf->AddLink(); + $objattr['link'] = $this->mpdf->internallink[$href]; + } else { + $objattr['link'] = $this->mpdf->HREF; + } + } + $extraheight = $objattr['padding_top'] + $objattr['padding_bottom'] + $objattr['margin_top'] + $objattr['margin_bottom'] + $objattr['border_top']['w'] + $objattr['border_bottom']['w']; + $extrawidth = $objattr['padding_left'] + $objattr['padding_right'] + $objattr['margin_left'] + $objattr['margin_right'] + $objattr['border_left']['w'] + $objattr['border_right']['w']; + + + $w = $objattr['r'] * 2; + $h = $w; + $objattr['height'] = $h + $extraheight; + $objattr['width'] = $w + $extrawidth; + $objattr['type'] = 'textcircle'; + + $e = Mpdf::OBJECT_IDENTIFIER . "type=image,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + + /* -- TABLES -- */ + // Output it to buffers + if ($this->mpdf->tableLevel) { + $this->mpdf->_saveCellTextBuffer($e, $this->mpdf->HREF); + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] += $objattr['width']; + } else { + /* -- END TABLES -- */ + $this->mpdf->_saveTextBuffer($e, $this->mpdf->HREF); + } // *TABLES* + + if ($this->mpdf->InlineProperties['TEXTCIRCLE']) { + $this->mpdf->restoreInlineProperties($this->mpdf->InlineProperties['TEXTCIRCLE']); + } + unset($this->mpdf->InlineProperties['TEXTCIRCLE']); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Th.php b/src/vendor/mpdf/mpdf/src/Tag/Th.php new file mode 100644 index 000000000..c0df792cd --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Th.php @@ -0,0 +1,13 @@ +<?php + +namespace Mpdf\Tag; + +class Th extends Td +{ + + public function close(&$ahtml, &$ihtml) + { + $this->mpdf->SetStyle('B', false); + parent::close($ahtml, $ihtml); + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Time.php b/src/vendor/mpdf/mpdf/src/Tag/Time.php new file mode 100644 index 000000000..04ffb6ea7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Time.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Time extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Toc.php b/src/vendor/mpdf/mpdf/src/Tag/Toc.php new file mode 100644 index 000000000..1afeae861 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Toc.php @@ -0,0 +1,17 @@ +<?php + +namespace Mpdf\Tag; + +class Toc extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + //added custom-tag - set Marker for insertion later of ToC + $this->tableOfContents->openTagTOC($attr); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TocEntry.php b/src/vendor/mpdf/mpdf/src/Tag/TocEntry.php new file mode 100644 index 000000000..2ba6e693e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TocEntry.php @@ -0,0 +1,40 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Mpdf; + +class TocEntry extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + if (!empty($attr['CONTENT'])) { + $objattr = []; + $objattr['CONTENT'] = htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES); + $objattr['type'] = 'toc'; + $objattr['vertical-align'] = 'T'; + if (!empty($attr['LEVEL'])) { + $objattr['toclevel'] = $attr['LEVEL']; + } else { + $objattr['toclevel'] = 0; + } + if (!empty($attr['NAME'])) { + $objattr['toc_id'] = $attr['NAME']; + } else { + $objattr['toc_id'] = 0; + } + $e = Mpdf::OBJECT_IDENTIFIER . "type=toc,objattr=" . serialize($objattr) . Mpdf::OBJECT_IDENTIFIER; + if ($this->mpdf->tableLevel) { + $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['textbuffer'][] = [$e]; + } // *TABLES* + else { // *TABLES* + $this->mpdf->textbuffer[] = [$e]; + } // *TABLES* + } + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/TocPageBreak.php b/src/vendor/mpdf/mpdf/src/Tag/TocPageBreak.php new file mode 100644 index 000000000..19c516763 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/TocPageBreak.php @@ -0,0 +1,16 @@ +<?php + +namespace Mpdf\Tag; + +class TocPageBreak extends FormFeed +{ + public function open($attr, &$ahtml, &$ihtml) + { + list($isbreak, $toc_id) = $this->tableOfContents->openTagTOCPAGEBREAK($attr); + $this->toc_id = $toc_id; + if ($isbreak) { + return; + } + parent::open($attr, $ahtml, $ihtml); + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Tr.php b/src/vendor/mpdf/mpdf/src/Tag/Tr.php new file mode 100644 index 000000000..1e9bdc6b3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Tr.php @@ -0,0 +1,115 @@ +<?php + +namespace Mpdf\Tag; + +use Mpdf\Css\Border; + +class Tr extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + + $this->mpdf->lastoptionaltag = 'TR'; // Save current HTML specified optional endtag + $this->cssManager->tbCSSlvl++; + $this->mpdf->row++; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nr'] ++; + $this->mpdf->col = -1; + $properties = $this->cssManager->MergeCSS('TABLE', 'TR', $attr); + + // write pagebreak markers into row list, so _tableWrite can respect it + if (isset($properties['PAGE-BREAK-BEFORE']) && strtoupper($properties['PAGE-BREAK-BEFORE']) === 'AVOID' + && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together && !isset($attr['PAGEBREAKAVOIDCHECKED'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['pagebreak-before'][$this->mpdf->row] = 'avoid'; + } + + if (isset($properties['PAGE-BREAK-AFTER']) && strtoupper($properties['PAGE-BREAK-AFTER']) === 'AVOID' + && !$this->mpdf->ColActive && !$this->mpdf->keep_block_together && !isset($attr['PAGEBREAKAVOIDCHECKED'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['pagebreak-before'][$this->mpdf->row + 1] = 'avoid'; + } + + if (!$this->mpdf->simpleTables && (!isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['borders_separate']) + || !$this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['borders_separate'])) { + if (!empty($properties['BORDER-LEFT'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-left'][$this->mpdf->row] = $properties['BORDER-LEFT']; + } + if (!empty($properties['BORDER-RIGHT'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-right'][$this->mpdf->row] = $properties['BORDER-RIGHT']; + } + if (!empty($properties['BORDER-TOP'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-top'][$this->mpdf->row] = $properties['BORDER-TOP']; + } + if (!empty($properties['BORDER-BOTTOM'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-bottom'][$this->mpdf->row] = $properties['BORDER-BOTTOM']; + } + } + + if (isset($properties['BACKGROUND-COLOR'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] : []; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$this->mpdf->row] = $properties['BACKGROUND-COLOR']; + } elseif (isset($attr['BGCOLOR'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] : []; + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$this->mpdf->row] = $attr['BGCOLOR']; + } + + /* -- BACKGROUNDS -- */ + if (isset($properties['BACKGROUND-GRADIENT']) && !$this->mpdf->kwt && !$this->mpdf->ColActive) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trgradients'][$this->mpdf->row] = $properties['BACKGROUND-GRADIENT']; + } + + // FIXME: undefined variable $currblk + if (!empty($properties['BACKGROUND-IMAGE']) && !$this->mpdf->kwt && !$this->mpdf->ColActive) { + $ret = $this->mpdf->SetBackground($properties, $currblk['inner_width']); + if ($ret) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trbackground-images'][$this->mpdf->row] = $ret; + } + } + /* -- END BACKGROUNDS -- */ + + if (isset($properties['TEXT-ROTATE'])) { + $this->mpdf->trow_text_rotate = $properties['TEXT-ROTATE']; + } + if (isset($attr['TEXT-ROTATE'])) { + $this->mpdf->trow_text_rotate = $attr['TEXT-ROTATE']; + } + + if ($this->mpdf->tablethead) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_thead'][$this->mpdf->row] = true; + } + if ($this->mpdf->tabletfoot) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['is_tfoot'][$this->mpdf->row] = true; + } + } + + public function close(&$ahtml, &$ihtml) + { + if ($this->mpdf->tableLevel) { + // If Border set on TR - Update right border + if (isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-left'][$this->mpdf->row])) { + $c = & $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]; + if ($c) { + if ($this->mpdf->packTableData) { + $cell = $this->mpdf->_unpackCellBorder($c['borderbin']); + } else { + $cell = $c; + } + $cell['border_details']['R'] = $this->mpdf->border_details( + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-right'][$this->mpdf->row] + ); + $this->mpdf->setBorder($cell['border'], Border::RIGHT, $cell['border_details']['R']['s']); + if ($this->mpdf->packTableData) { + $c['borderbin'] = $this->mpdf->_packCellBorder($cell); + unset($c['border'], $c['border_details']); + } else { + $c = $cell; + } + } + } + $this->mpdf->lastoptionaltag = ''; + unset($this->cssManager->tablecascadeCSS[$this->cssManager->tbCSSlvl]); + $this->cssManager->tbCSSlvl--; + $this->mpdf->trow_text_rotate = ''; + $this->mpdf->tabletheadjustfinished = false; + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Tt.php b/src/vendor/mpdf/mpdf/src/Tag/Tt.php new file mode 100644 index 000000000..078277ad8 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Tt.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Tt extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Tta.php b/src/vendor/mpdf/mpdf/src/Tag/Tta.php new file mode 100644 index 000000000..bac9fb57e --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Tta.php @@ -0,0 +1,22 @@ +<?php + +namespace Mpdf\Tag; + +class Tta extends SubstituteTag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->tta = true; + $this->mpdf->InlineProperties['TTA'] = $this->mpdf->saveInlineProperties(); + + if (in_array($this->mpdf->FontFamily, $this->mpdf->mono_fonts)) { + $this->mpdf->setCSS(['FONT-FAMILY' => 'ccourier'], 'INLINE'); + } elseif (in_array($this->mpdf->FontFamily, $this->mpdf->serif_fonts)) { + $this->mpdf->setCSS(['FONT-FAMILY' => 'ctimes'], 'INLINE'); + } else { + $this->mpdf->setCSS(['FONT-FAMILY' => 'chelvetica'], 'INLINE'); + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Tts.php b/src/vendor/mpdf/mpdf/src/Tag/Tts.php new file mode 100644 index 000000000..f24d722cf --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Tts.php @@ -0,0 +1,15 @@ +<?php + +namespace Mpdf\Tag; + +class Tts extends SubstituteTag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->tts = true; + $this->mpdf->InlineProperties['TTS'] = $this->mpdf->saveInlineProperties(); + $this->mpdf->setCSS(['FONT-FAMILY' => 'csymbol', 'FONT-WEIGHT' => 'normal', 'FONT-STYLE' => 'normal'], 'INLINE'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Ttz.php b/src/vendor/mpdf/mpdf/src/Tag/Ttz.php new file mode 100644 index 000000000..d76d4c553 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Ttz.php @@ -0,0 +1,15 @@ +<?php + +namespace Mpdf\Tag; + +class Ttz extends SubstituteTag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $this->mpdf->ttz = true; + $this->mpdf->InlineProperties['TTZ'] = $this->mpdf->saveInlineProperties(); + $this->mpdf->setCSS(['FONT-FAMILY' => 'czapfdingbats', 'FONT-WEIGHT' => 'normal', 'FONT-STYLE' => 'normal'], 'INLINE'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/U.php b/src/vendor/mpdf/mpdf/src/Tag/U.php new file mode 100644 index 000000000..513298d72 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/U.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class U extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/Ul.php b/src/vendor/mpdf/mpdf/src/Tag/Ul.php new file mode 100644 index 000000000..6efa4d6cb --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/Ul.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class Ul extends BlockTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/VarTag.php b/src/vendor/mpdf/mpdf/src/Tag/VarTag.php new file mode 100644 index 000000000..556dd40e1 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/VarTag.php @@ -0,0 +1,9 @@ +<?php + +namespace Mpdf\Tag; + +class VarTag extends InlineTag +{ + + +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/WatermarkImage.php b/src/vendor/mpdf/mpdf/src/Tag/WatermarkImage.php new file mode 100644 index 000000000..21f8c48b5 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/WatermarkImage.php @@ -0,0 +1,41 @@ +<?php + +namespace Mpdf\Tag; + +class WatermarkImage extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $src = ''; + if (isset($attr['SRC'])) { + $src = $attr['SRC']; + } + + $alpha = -1; + if (isset($attr['ALPHA']) && $attr['ALPHA'] > 0) { + $alpha = $attr['ALPHA']; + } + + $size = 'D'; + if (!empty($attr['SIZE'])) { + $size = $attr['SIZE']; + if (strpos($size, ',')) { + $size = explode(',', $size); + } + } + + $pos = 'P'; + if (!empty($attr['POSITION'])) { // mPDF 5.7.2 + $pos = $attr['POSITION']; + if (strpos($pos, ',')) { + $pos = explode(',', $pos); + } + } + $this->mpdf->SetWatermarkImage($src, $alpha, $size, $pos); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Tag/WatermarkText.php b/src/vendor/mpdf/mpdf/src/Tag/WatermarkText.php new file mode 100644 index 000000000..8d6dcc2dc --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Tag/WatermarkText.php @@ -0,0 +1,25 @@ +<?php + +namespace Mpdf\Tag; + +class WatermarkText extends Tag +{ + + public function open($attr, &$ahtml, &$ihtml) + { + $txt = ''; + if (!empty($attr['CONTENT'])) { + $txt = htmlspecialchars_decode($attr['CONTENT'], ENT_QUOTES); + } + + $alpha = -1; + if (isset($attr['ALPHA']) && $attr['ALPHA'] > 0) { + $alpha = $attr['ALPHA']; + } + $this->mpdf->SetWatermarkText($txt, $alpha); + } + + public function close(&$ahtml, &$ihtml) + { + } +} diff --git a/src/vendor/mpdf/mpdf/src/Ucdn.php b/src/vendor/mpdf/mpdf/src/Ucdn.php new file mode 100644 index 000000000..dbf7caaec --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Ucdn.php @@ -0,0 +1,2921 @@ +<?php + +namespace Mpdf; + +class Ucdn +{ + + /* HarfBuzz ucdn/unicodedata_db.h */ + /* HarfBuzz ucdn/ucdn.c */ + /* HarfBuzz ucdn/ucdn.h */ + + const SCRIPT_COMMON = 0; + const SCRIPT_LATIN = 1; + const SCRIPT_GREEK = 2; + const SCRIPT_CYRILLIC = 3; + const SCRIPT_ARMENIAN = 4; + const SCRIPT_HEBREW = 5; + const SCRIPT_ARABIC = 6; + const SCRIPT_SYRIAC = 7; + const SCRIPT_THAANA = 8; + const SCRIPT_DEVANAGARI = 9; + const SCRIPT_BENGALI = 10; + const SCRIPT_GURMUKHI = 11; + const SCRIPT_GUJARATI = 12; + const SCRIPT_ORIYA = 13; + const SCRIPT_TAMIL = 14; + const SCRIPT_TELUGU = 15; + const SCRIPT_KANNADA = 16; + const SCRIPT_MALAYALAM = 17; + const SCRIPT_SINHALA = 18; + const SCRIPT_THAI = 19; + const SCRIPT_LAO = 20; + const SCRIPT_TIBETAN = 21; + const SCRIPT_MYANMAR = 22; + const SCRIPT_GEORGIAN = 23; + const SCRIPT_HANGUL = 24; + const SCRIPT_ETHIOPIC = 25; + const SCRIPT_CHEROKEE = 26; + const SCRIPT_CANADIAN_ABORIGINAL = 27; + const SCRIPT_OGHAM = 28; + const SCRIPT_RUNIC = 29; + const SCRIPT_KHMER = 30; + const SCRIPT_MONGOLIAN = 31; + const SCRIPT_HIRAGANA = 32; + const SCRIPT_KATAKANA = 33; + const SCRIPT_BOPOMOFO = 34; + const SCRIPT_HAN = 35; + const SCRIPT_YI = 36; + const SCRIPT_OLD_ITALIC = 37; + const SCRIPT_GOTHIC = 38; + const SCRIPT_DESERET = 39; + const SCRIPT_INHERITED = 40; + const SCRIPT_TAGALOG = 41; + const SCRIPT_HANUNOO = 42; + const SCRIPT_BUHID = 43; + const SCRIPT_TAGBANWA = 44; + const SCRIPT_LIMBU = 45; + const SCRIPT_TAI_LE = 46; + const SCRIPT_LINEAR_B = 47; + const SCRIPT_UGARITIC = 48; + const SCRIPT_SHAVIAN = 49; + const SCRIPT_OSMANYA = 50; + const SCRIPT_CYPRIOT = 51; + const SCRIPT_BRAILLE = 52; + const SCRIPT_BUGINESE = 53; + const SCRIPT_COPTIC = 54; + const SCRIPT_NEW_TAI_LUE = 55; + const SCRIPT_GLAGOLITIC = 56; + const SCRIPT_TIFINAGH = 57; + const SCRIPT_SYLOTI_NAGRI = 58; + const SCRIPT_OLD_PERSIAN = 59; + const SCRIPT_KHAROSHTHI = 60; + const SCRIPT_BALINESE = 61; + const SCRIPT_CUNEIFORM = 62; + const SCRIPT_PHOENICIAN = 63; + const SCRIPT_PHAGS_PA = 64; + const SCRIPT_NKO = 65; + const SCRIPT_SUNDANESE = 66; + const SCRIPT_LEPCHA = 67; + const SCRIPT_OL_CHIKI = 68; + const SCRIPT_VAI = 69; + const SCRIPT_SAURASHTRA = 70; + const SCRIPT_KAYAH_LI = 71; + const SCRIPT_REJANG = 72; + const SCRIPT_LYCIAN = 73; + const SCRIPT_CARIAN = 74; + const SCRIPT_LYDIAN = 75; + const SCRIPT_CHAM = 76; + const SCRIPT_TAI_THAM = 77; + const SCRIPT_TAI_VIET = 78; + const SCRIPT_AVESTAN = 79; + const SCRIPT_EGYPTIAN_HIEROGLYPHS = 80; + const SCRIPT_SAMARITAN = 81; + const SCRIPT_LISU = 82; + const SCRIPT_BAMUM = 83; + const SCRIPT_JAVANESE = 84; + const SCRIPT_MEETEI_MAYEK = 85; + const SCRIPT_IMPERIAL_ARAMAIC = 86; + const SCRIPT_OLD_SOUTH_ARABIAN = 87; + const SCRIPT_INSCRIPTIONAL_PARTHIAN = 88; + const SCRIPT_INSCRIPTIONAL_PAHLAVI = 89; + const SCRIPT_OLD_TURKIC = 90; + const SCRIPT_KAITHI = 91; + const SCRIPT_BATAK = 92; + const SCRIPT_BRAHMI = 93; + const SCRIPT_MANDAIC = 94; + const SCRIPT_CHAKMA = 95; + const SCRIPT_MEROITIC_CURSIVE = 96; + const SCRIPT_MEROITIC_HIEROGLYPHS = 97; + const SCRIPT_MIAO = 98; + const SCRIPT_SHARADA = 99; + const SCRIPT_SORA_SOMPENG = 100; + const SCRIPT_TAKRI = 101; + const SCRIPT_UNKNOWN = 102; + + public static function get_ucd_record($code) + { + if ($code >= 0x110000) { + $index = 0; + } else { + $index = self::$index0[$code >> (8)] << 5; + $offset = ($code >> 3) & ((1 << 5) - 1); + $index = self::$index1[$index + $offset] << 3; + $offset = $code & ((1 << 3) - 1); + $index = self::$index2[$index + $offset]; + } + return self::$ucd_records[$index]; + } + + public static function get_general_category($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[0]; + } + + public static function get_combining_class($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[1]; + } + + public static function get_bidi_class($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[2]; + } + + public static function get_mirrored($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[3]; + } + + public static function get_east_asian_width($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[4]; + } + + public static function get_normalization_check($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[5]; + } + + public static function get_script($code) + { + $ucd_record = self::get_ucd_record($code); + return $ucd_record[6]; + } + + // mPDF added + public static $uni_scriptblock = [ + /* SCRIPT_COMMON */ 0 => '', + /* SCRIPT_LATIN */ 1 => 'latn', + /* SCRIPT_GREEK */ 2 => 'grek', + /* SCRIPT_CYRILLIC */ 3 => 'cyrl', + /* SCRIPT_ARMENIAN */ 4 => 'armn', + /* SCRIPT_HEBREW */ 5 => 'hebr', + /* SCRIPT_ARABIC */ 6 => 'arab', + /* SCRIPT_SYRIAC */ 7 => 'syrc', + /* SCRIPT_THAANA */ 8 => 'thaa', + /* SCRIPT_DEVANAGARI */ 9 => 'dev2', + /* SCRIPT_BENGALI */ 10 => 'bng2', + /* SCRIPT_GURMUKHI */ 11 => 'gur2', + /* SCRIPT_GUJARATI */ 12 => 'gjr2', + /* SCRIPT_ORIYA */ 13 => 'ory2', + /* SCRIPT_TAMIL */ 14 => 'tml2', + /* SCRIPT_TELUGU */ 15 => 'tel2', + /* SCRIPT_KANNADA */ 16 => 'knd2', + /* SCRIPT_MALAYALAM */ 17 => 'mlm2', + /* SCRIPT_SINHALA */ 18 => 'sinh', + /* SCRIPT_THAI */ 19 => 'thai', + /* SCRIPT_LAO */ 20 => 'lao ', + /* SCRIPT_TIBETAN */ 21 => 'tibt', + /* SCRIPT_MYANMAR */ 22 => 'mym2', + /* SCRIPT_GEORGIAN */ 23 => 'geor', + /* SCRIPT_HANGUL */ 24 => 'jamo', /* there is also a hang tag, but we want to activate jamo features if present */ + /* SCRIPT_ETHIOPIC */ 25 => 'ethi', + /* SCRIPT_CHEROKEE */ 26 => 'cher', + /* SCRIPT_CANADIAN_ABORIGINAL */ 27 => 'cans', + /* SCRIPT_OGHAM */ 28 => 'ogam', + /* SCRIPT_RUNIC */ 29 => 'runr', + /* SCRIPT_KHMER */ 30 => 'khmr', + /* SCRIPT_MONGOLIAN */ 31 => 'mong', + /* SCRIPT_HIRAGANA */ 32 => 'kana', + /* SCRIPT_KATAKANA */ 33 => 'kana', + /* SCRIPT_BOPOMOFO */ 34 => 'bopo', + /* SCRIPT_HAN */ 35 => 'hani', + /* SCRIPT_YI */ 36 => 'yi ', + /* SCRIPT_OLD_ITALIC */ 37 => 'ital', + /* SCRIPT_GOTHIC */ 38 => 'goth', + /* SCRIPT_DESERET */ 39 => 'dsrt', + /* SCRIPT_INHERITED */ 40 => '', + /* SCRIPT_TAGALOG */ 41 => 'tglg', + /* SCRIPT_HANUNOO */ 42 => 'hano', + /* SCRIPT_BUHID */ 43 => 'buhd', + /* SCRIPT_TAGBANWA */ 44 => 'tagb', + /* SCRIPT_LIMBU */ 45 => 'limb', + /* SCRIPT_TAI_LE */ 46 => 'tale', + /* SCRIPT_LINEAR_B */ 47 => 'linb', + /* SCRIPT_UGARITIC */ 48 => 'ugar', + /* SCRIPT_SHAVIAN */ 49 => 'shaw', + /* SCRIPT_OSMANYA */ 50 => 'osma', + /* SCRIPT_CYPRIOT */ 51 => 'cprt', + /* SCRIPT_BRAILLE */ 52 => 'brai', + /* SCRIPT_BUGINESE */ 53 => 'bugi', + /* SCRIPT_COPTIC */ 54 => 'copt', + /* SCRIPT_NEW_TAI_LUE */ 55 => 'talu', + /* SCRIPT_GLAGOLITIC */ 56 => 'glag', + /* SCRIPT_TIFINAGH */ 57 => 'tfng', + /* SCRIPT_SYLOTI_NAGRI */ 58 => 'sylo', + /* SCRIPT_OLD_PERSIAN */ 59 => 'xpeo', + /* SCRIPT_KHAROSHTHI */ 60 => 'khar', + /* SCRIPT_BALINESE */ 61 => 'bali', + /* SCRIPT_CUNEIFORM */ 62 => 'xsux', + /* SCRIPT_PHOENICIAN */ 63 => 'phnx', + /* SCRIPT_PHAGS_PA */ 64 => 'phag', + /* SCRIPT_NKO */ 65 => 'nko ', + /* SCRIPT_SUNDANESE */ 66 => 'sund', + /* SCRIPT_LEPCHA */ 67 => 'lepc', + /* SCRIPT_OL_CHIKI */ 68 => 'olck', + /* SCRIPT_VAI */ 69 => 'vai ', + /* SCRIPT_SAURASHTRA */ 70 => 'saur', + /* SCRIPT_KAYAH_LI */ 71 => 'kali', + /* SCRIPT_REJANG */ 72 => 'rjng', + /* SCRIPT_LYCIAN */ 73 => 'lyci', + /* SCRIPT_CARIAN */ 74 => 'cari', + /* SCRIPT_LYDIAN */ 75 => 'lydi', + /* SCRIPT_CHAM */ 76 => 'cham', + /* SCRIPT_TAI_THAM */ 77 => 'lana', + /* SCRIPT_TAI_VIET */ 78 => 'tavt', + /* SCRIPT_AVESTAN */ 79 => 'avst', + /* SCRIPT_EGYPTIAN_HIEROGLYPHS */ 80 => 'egyp', + /* SCRIPT_SAMARITAN */ 81 => 'samr', + /* SCRIPT_LISU */ 82 => 'lisu', + /* SCRIPT_BAMUM */ 83 => 'bamu', + /* SCRIPT_JAVANESE */ 84 => 'java', + /* SCRIPT_MEETEI_MAYEK */ 85 => 'mtei', + /* SCRIPT_IMPERIAL_ARAMAIC */ 86 => 'armi', + /* SCRIPT_OLD_SOUTH_ARABIAN */ 87 => 'sarb', + /* SCRIPT_INSCRIPTIONAL_PARTHIAN */ 88 => 'prti', + /* SCRIPT_INSCRIPTIONAL_PAHLAVI */ 89 => 'phli', + /* SCRIPT_OLD_TURKIC */ 90 => 'orkh', + /* SCRIPT_KAITHI */ 91 => 'kthi', + /* SCRIPT_BATAK */ 92 => 'batk', + /* SCRIPT_BRAHMI */ 93 => 'brah', + /* SCRIPT_MANDAIC */ 94 => 'mand', + /* SCRIPT_CHAKMA */ 95 => 'cakm', + /* SCRIPT_MEROITIC_CURSIVE */ 96 => 'merc', + /* SCRIPT_MEROITIC_HIEROGLYPHS */ 97 => 'mero', + /* SCRIPT_MIAO */ 98 => 'plrd', + /* SCRIPT_SHARADA */ 99 => 'shrd', + /* SCRIPT_SORA_SOMPENG */ 100 => 'sora', + /* SCRIPT_TAKRI */ 101 => 'takr', + /* SCRIPT_UNKNOWN */ 102 => '', + ]; + + public static $ot_languages = [ + 'aa' => 'AFR ', /* Afar */ + 'ab' => 'ABK ', /* Abkhazian */ + 'abq' => 'ABA ', /* Abaza */ + 'ada' => 'DNG ', /* Dangme */ + 'ady' => 'ADY ', /* Adyghe */ + 'af' => 'AFK ', /* Afrikaans */ + 'aii' => 'SWA ', /* Swadaya Aramaic */ + 'aiw' => 'ARI ', /* Aari */ + 'alt' => 'ALT ', /* [Southern] Altai */ + 'am' => 'AMH ', /* Amharic */ + 'amf' => 'HBN ', /* Hammer-Banna */ + 'ar' => 'ARA ', /* Arabic */ + 'arn' => 'MAP ', /* Mapudungun */ + 'as' => 'ASM ', /* Assamese */ + 'ath' => 'ATH ', /* Athapaskan [family] */ + 'atv' => 'ALT ', /* [Northern] Altai */ + 'av' => 'AVR ', /* Avaric */ + 'awa' => 'AWA ', /* Awadhi */ + 'ay' => 'AYM ', /* Aymara */ + 'az' => 'AZE ', /* Azerbaijani */ + 'ba' => 'BSH ', /* Bashkir */ + 'bai' => 'BML ', /* Bamileke [family] */ + 'bal' => 'BLI ', /* Baluchi */ + 'bci' => 'BAU ', /* Baule */ + 'bcq' => 'BCH ', /* Bench */ + 'be' => 'BEL ', /* Belarussian */ + 'bem' => 'BEM ', /* Bemba (Zambia) */ + 'ber' => 'BER ', /* Berber [family] */ + 'bfq' => 'BAD ', /* Badaga */ + 'bft' => 'BLT ', /* Balti */ + 'bfy' => 'BAG ', /* Baghelkhandi */ + 'bg' => 'BGR ', /* Bulgarian */ + 'bhb' => 'BHI ', /* Bhili */ + 'bho' => 'BHO ', /* Bhojpuri */ + 'bik' => 'BIK ', /* Bikol */ + 'bin' => 'EDO ', /* Bini */ + 'bjt' => 'BLN ', /* Balanta-Ganja */ + 'bla' => 'BKF ', /* Blackfoot */ + 'ble' => 'BLN ', /* Balanta-Kentohe */ + 'bm' => 'BMB ', /* Bambara */ + 'bn' => 'BEN ', /* Bengali */ + 'bo' => 'TIB ', /* Tibetan */ + 'br' => 'BRE ', /* Breton */ + 'bra' => 'BRI ', /* Braj Bhasha */ + 'brh' => 'BRH ', /* Brahui */ + 'bs' => 'BOS ', /* Bosnian */ + 'btb' => 'BTI ', /* Beti (Cameroon) */ + 'bxr' => 'RBU ', /* Russian Buriat */ + 'byn' => 'BIL ', /* Bilen */ + 'ca' => 'CAT ', /* Catalan */ + 'ce' => 'CHE ', /* Chechen */ + 'ceb' => 'CEB ', /* Cebuano */ + 'chp' => 'CHP ', /* Chipewyan */ + 'chr' => 'CHR ', /* Cherokee */ + 'ckt' => 'CHK ', /* Chukchi */ + 'cop' => 'COP ', /* Coptic */ + 'cr' => 'CRE ', /* Cree */ + 'crh' => 'CRT ', /* Crimean Tatar */ + 'crj' => 'ECR ', /* [Southern] East Cree */ + 'crl' => 'ECR ', /* [Northern] East Cree */ + 'crm' => 'MCR ', /* Moose Cree */ + 'crx' => 'CRR ', /* Carrier */ + 'cs' => 'CSY ', /* Czech */ + 'cu' => 'CSL ', /* Church Slavic */ + 'cv' => 'CHU ', /* Chuvash */ + 'cwd' => 'DCR ', /* Woods Cree */ + 'cy' => 'WEL ', /* Welsh */ + 'da' => 'DAN ', /* Danish */ + 'dap' => 'NIS ', /* Nisi (India) */ + 'dar' => 'DAR ', /* Dargwa */ + 'de' => 'DEU ', /* German */ + 'din' => 'DNK ', /* Dinka */ + 'dje' => 'DJR ', /* Djerma */ + 'dng' => 'DUN ', /* Dungan */ + 'doi' => 'DGR ', /* Dogri */ + 'dsb' => 'LSB ', /* Lower Sorbian */ + 'dv' => 'DIV ', /* Dhivehi */ + 'dyu' => 'JUL ', /* Jula */ + 'dz' => 'DZN ', /* Dzongkha */ + 'ee' => 'EWE ', /* Ewe */ + 'efi' => 'EFI ', /* Efik */ + 'el' => 'ELL ', /* Modern Greek (1453-) */ + 'grc' => 'PGR ', /* Polytonic Greek */ + 'en' => 'ENG ', /* English */ + 'eo' => 'NTO ', /* Esperanto */ + 'eot' => 'BTI ', /* Beti (Côte d'Ivoire) */ + 'es' => 'ESP ', /* Spanish */ + 'et' => 'ETI ', /* Estonian */ + 'eu' => 'EUQ ', /* Basque */ + 'eve' => 'EVN ', /* Even */ + 'evn' => 'EVK ', /* Evenki */ + 'fa' => 'FAR ', /* Persian */ + 'ff' => 'FUL ', /* Fulah */ + 'fi' => 'FIN ', /* Finnish */ + 'fil' => 'PIL ', /* Filipino */ + 'fj' => 'FJI ', /* Fijian */ + 'fo' => 'FOS ', /* Faroese */ + 'fon' => 'FON ', /* Fon */ + 'fr' => 'FRA ', /* French */ + 'fur' => 'FRL ', /* Friulian */ + 'fy' => 'FRI ', /* Western Frisian */ + 'ga' => 'IRI ', /* Irish */ + 'gaa' => 'GAD ', /* Ga */ + 'gag' => 'GAG ', /* Gagauz */ + 'gbm' => 'GAW ', /* Garhwali */ + 'gd' => 'GAE ', /* Scottish Gaelic */ + 'gez' => 'GEZ ', /* Ge'ez */ + 'gl' => 'GAL ', /* Galician */ + 'gld' => 'NAN ', /* Nanai */ + 'gn' => 'GUA ', /* Guarani */ + 'gon' => 'GON ', /* Gondi */ + 'grt' => 'GRO ', /* Garo */ + 'gru' => 'SOG ', /* Sodo Gurage */ + 'gu' => 'GUJ ', /* Gujarati */ + 'guk' => 'GMZ ', /* Gumuz */ + 'gv' => 'MNX ', /* Manx Gaelic */ + 'ha' => 'HAU ', /* Hausa */ + 'har' => 'HRI ', /* Harari */ + 'haw' => 'HAW ', /* Hawaiin */ + 'he' => 'IWR ', /* Hebrew */ + 'hi' => 'HIN ', /* Hindi */ + 'hil' => 'HIL ', /* Hiligaynon */ + 'hnd' => 'HND ', /* [Southern] Hindko */ + 'hne' => 'CHH ', /* Chattisgarhi */ + 'hno' => 'HND ', /* [Northern] Hindko */ + 'hoc' => 'HO ', /* Ho */ + 'hoj' => 'HAR ', /* Harauti */ + 'hr' => 'HRV ', /* Croatian */ + 'hsb' => 'USB ', /* Upper Sorbian */ + 'ht' => 'HAI ', /* Haitian */ + 'hu' => 'HUN ', /* Hungarian */ + 'hy' => 'HYE ', /* Armenian */ + 'id' => 'IND ', /* Indonesian */ + 'ig' => 'IBO ', /* Igbo */ + 'igb' => 'EBI ', /* Ebira */ + 'ijo' => 'IJO ', /* Ijo [family] */ + 'ilo' => 'ILO ', /* Ilokano */ + 'inh' => 'ING ', /* Ingush */ + 'is' => 'ISL ', /* Icelandic */ + 'it' => 'ITA ', /* Italian */ + 'iu' => 'INU ', /* Inuktitut */ + 'ja' => 'JAN ', /* Japanese */ + 'jv' => 'JAV ', /* Javanese */ + 'ka' => 'KAT ', /* Georgian */ + 'kaa' => 'KRK ', /* Karakalpak */ + 'kam' => 'KMB ', /* Kamba (Kenya) */ + 'kar' => 'KRN ', /* Karen [family] */ + 'kbd' => 'KAB ', /* Kabardian */ + 'kdr' => 'KRM ', /* Karaim */ + 'kdt' => 'KUY ', /* Kuy */ + 'kex' => 'KKN ', /* Kokni */ + 'kfr' => 'KAC ', /* Kachchi */ + 'kfy' => 'KMN ', /* Kumaoni */ + 'kha' => 'KSI ', /* Khasi */ + 'khb' => 'XBD ', /* Tai Lue */ + 'khw' => 'KHW ', /* Khowar */ + 'ki' => 'KIK ', /* Kikuyu */ + 'kjh' => 'KHA ', /* Khakass */ + 'kk' => 'KAZ ', /* Kazakh */ + 'kl' => 'GRN ', /* Kalaallisut */ + 'kln' => 'KAL ', /* Kalenjin */ + 'km' => 'KHM ', /* Central Khmer */ + 'kmb' => 'MBN ', /* [North] Mbundu */ + 'kmw' => 'KMO ', /* Komo (Democratic Republic of Congo) */ + 'kn' => 'KAN ', /* Kannada */ + 'ko' => 'KOR ', /* Korean */ + 'koi' => 'KOP ', /* Komi-Permyak */ + 'kok' => 'KOK ', /* Konkani */ + 'kpe' => 'KPL ', /* Kpelle */ + 'kpv' => 'KOZ ', /* Komi-Zyrian */ + 'kpy' => 'KYK ', /* Koryak */ + 'kqy' => 'KRT ', /* Koorete */ + 'kr' => 'KNR ', /* Kanuri */ + 'kri' => 'KRI ', /* Krio */ + 'krl' => 'KRL ', /* Karelian */ + 'kru' => 'KUU ', /* Kurukh */ + 'ks' => 'KSH ', /* Kashmiri */ + 'ku' => 'KUR ', /* Kurdish */ + 'kum' => 'KUM ', /* Kumyk */ + 'kvd' => 'KUI ', /* Kui (Indonesia) */ + 'kxc' => 'KMS ', /* Komso */ + 'kxu' => 'KUI ', /* Kui (India) */ + 'ky' => 'KIR ', /* Kirghiz */ + 'la' => 'LAT ', /* Latin */ + 'lad' => 'JUD ', /* Ladino */ + 'lb' => 'LTZ ', /* Luxembourgish */ + 'lbe' => 'LAK ', /* Lak */ + 'lbj' => 'LDK ', /* Ladakhi */ + 'lez' => 'LEZ ', /* Lezgi */ + 'lg' => 'LUG ', /* Luganda */ + 'lif' => 'LMB ', /* Limbu */ + 'lld' => 'LAD ', /* Ladin */ + 'lmn' => 'LAM ', /* Lambani */ + 'ln' => 'LIN ', /* Lingala */ + 'lo' => 'LAO ', /* Lao */ + 'lt' => 'LTH ', /* Lithuanian */ + 'lu' => 'LUB ', /* Luba-Katanga */ + 'lua' => 'LUB ', /* Luba-Kasai */ + 'luo' => 'LUO ', /* Luo (Kenya and Tanzania) */ + 'lus' => 'MIZ ', /* Mizo */ + 'luy' => 'LUH ', /* Luhya [macrolanguage] */ + 'lv' => 'LVI ', /* Latvian */ + 'lzz' => 'LAZ ', /* Laz */ + 'mai' => 'MTH ', /* Maithili */ + 'mdc' => 'MLE ', /* Male (Papua New Guinea) */ + 'mdf' => 'MOK ', /* Moksha */ + 'mdy' => 'MLE ', /* Male (Ethiopia) */ + 'men' => 'MDE ', /* Mende (Sierra Leone) */ + 'mg' => 'MLG ', /* Malagasy */ + 'mhr' => 'LMA ', /* Low Mari */ + 'mi' => 'MRI ', /* Maori */ + 'mk' => 'MKD ', /* Macedonian */ + 'ml' => 'MLR ', /* Malayalam reformed (MAL is Malayalam Traditional) */ + 'mn' => 'MNG ', /* Mongolian */ + 'mnc' => 'MCH ', /* Manchu */ + 'mni' => 'MNI ', /* Manipuri */ + 'mnk' => 'MND ', /* Mandinka */ + 'mns' => 'MAN ', /* Mansi */ + 'mnw' => 'MON ', /* Mon */ + 'mo' => 'MOL ', /* Moldavian */ + 'moh' => 'MOH ', /* Mohawk */ + 'mpe' => 'MAJ ', /* Majang */ + 'mr' => 'MAR ', /* Marathi */ + 'mrj' => 'HMA ', /* High Mari */ + 'ms' => 'MLY ', /* Malay */ + 'mt' => 'MTS ', /* Maltese */ + 'mwr' => 'MAW ', /* Marwari */ + 'my' => 'BRM ', /* Burmese */ + 'mym' => 'MEN ', /* Me'en */ + 'myv' => 'ERZ ', /* Erzya */ + 'nag' => 'NAG ', /* Naga-Assamese */ + 'nb' => 'NOR ', /* Norwegian Bokmål */ + 'nco' => 'SIB ', /* Sibe */ + 'nd' => 'NDB ', /* [North] Ndebele */ + 'ne' => 'NEP ', /* Nepali */ + 'new' => 'NEW ', /* Newari */ + 'ng' => 'NDG ', /* Ndonga */ + 'ngl' => 'LMW ', /* Lomwe */ + 'niu' => 'NIU ', /* Niuean */ + 'niv' => 'GIL ', /* Gilyak */ + 'nl' => 'NLD ', /* Dutch */ + 'nn' => 'NYN ', /* Norwegian Nynorsk */ + 'no' => 'NOR ', /* Norwegian (deprecated) */ + 'nod' => 'NTA ', /* Northern Tai */ + 'nog' => 'NOG ', /* Nogai */ + 'nqo' => 'NKO ', /* N'Ko */ + 'nr' => 'NDB ', /* [South] Ndebele */ + 'nsk' => 'NAS ', /* Naskapi */ + 'nso' => 'SOT ', /* [Northern] Sotho */ + 'ny' => 'CHI ', /* Nyanja */ + 'nyn' => 'NKL ', /* Nkole */ + 'oc' => 'OCI ', /* Occitan (post 1500) */ + 'oj' => 'OJB ', /* Ojibwa */ + 'ojs' => 'OCR ', /* Oji-Cree */ + 'om' => 'ORO ', /* Oromo */ + 'or' => 'ORI ', /* Oriya */ + 'os' => 'OSS ', /* Ossetian */ + 'pa' => 'PAN ', /* Panjabi */ + 'pce' => 'PLG ', /* [Ruching] Palaung */ + 'pi' => 'PAL ', /* Pali */ + 'pl' => 'PLK ', /* Polish */ + 'pll' => 'PLG ', /* [Shwe] Palaung */ + 'plp' => 'PAP ', /* Palpa */ + 'prs' => 'DRI ', /* Dari */ + 'ps' => 'PAS ', /* Pushto */ + 'pt' => 'PTG ', /* Portuguese */ + 'raj' => 'RAJ ', /* Rajasthani */ + 'rbb' => 'PLG ', /* [Rumai] Palaung */ + 'ria' => 'RIA ', /* Riang (India) */ + 'ril' => 'RIA ', /* Riang (Myanmar) */ + 'rki' => 'ARK ', /* Arakanese */ + 'rm' => 'RMS ', /* Rhaeto-Romanic */ + 'ro' => 'ROM ', /* Romanian */ + 'rom' => 'ROY ', /* Romany */ + 'ru' => 'RUS ', /* Russian */ + 'rue' => 'RSY ', /* Rusyn */ + 'rw' => 'RUA ', /* Ruanda */ + 'sa' => 'SAN ', /* Sanskrit */ + 'sah' => 'YAK ', /* Yakut */ + 'sat' => 'SAT ', /* Santali */ + 'sck' => 'SAD ', /* Sadri */ + 'scs' => 'SLA ', /* [North] Slavey */ + 'sd' => 'SND ', /* Sindhi */ + 'se' => 'NSM ', /* Northern Sami */ + 'seh' => 'SNA ', /* Sena */ + 'sel' => 'SEL ', /* Selkup */ + 'sg' => 'SGO ', /* Sango */ + 'shn' => 'SHN ', /* Shan */ + 'si' => 'SNH ', /* Sinhala */ + 'sid' => 'SID ', /* Sidamo */ + 'sjd' => 'KSM ', /* Kildin Sami */ + 'sk' => 'SKY ', /* Slovak */ + 'skr' => 'SRK ', /* Seraiki */ + 'sl' => 'SLV ', /* Slovenian */ + 'sm' => 'SMO ', /* Samoan */ + 'sma' => 'SSM ', /* Southern Sami */ + 'smj' => 'LSM ', /* Lule Sami */ + 'smn' => 'ISM ', /* Inari Sami */ + 'sms' => 'SKS ', /* Skolt Sami */ + 'snk' => 'SNK ', /* Soninke */ + 'so' => 'SML ', /* Somali */ + 'sq' => 'SQI ', /* Albanian */ + 'sr' => 'SRB ', /* Serbian */ + 'srr' => 'SRR ', /* Serer */ + 'ss' => 'SWZ ', /* Swazi */ + 'st' => 'SOT ', /* [Southern] Sotho */ + 'suq' => 'SUR ', /* Suri */ + 'sv' => 'SVE ', /* Swedish */ + 'sva' => 'SVA ', /* Svan */ + 'sw' => 'SWK ', /* Swahili */ + 'swb' => 'CMR ', /* Comorian */ + 'syr' => 'SYR ', /* Syriac */ + 'ta' => 'TAM ', /* Tamil */ + 'tab' => 'TAB ', /* Tabasaran */ + 'tcy' => 'TUL ', /* Tulu */ + 'te' => 'TEL ', /* Telugu */ + 'tem' => 'TMN ', /* Temne */ + 'tg' => 'TAJ ', /* Tajik */ + 'th' => 'THA ', /* Thai */ + 'ti' => 'TGY ', /* Tigrinya */ + 'tig' => 'TGR ', /* Tigre */ + 'tk' => 'TKM ', /* Turkmen */ + 'tn' => 'TNA ', /* Tswana */ + 'to' => 'TGN ', /* Tonga (Tonga Islands) */ + 'tr' => 'TRK ', /* Turkish */ + 'tru' => 'TUA ', /* Turoyo Aramaic */ + 'ts' => 'TSG ', /* Tsonga */ + 'tt' => 'TAT ', /* Tatar */ + 'tw' => 'TWI ', /* Twi */ + 'ty' => 'THT ', /* Tahitian */ + 'tyv' => 'TUV ', /* Tuvin */ + 'udm' => 'UDM ', /* Udmurt */ + 'ug' => 'UYG ', /* Uighur */ + 'uk' => 'UKR ', /* Ukrainian */ + 'umb' => 'MBN ', /* [South] Mbundu */ + 'unr' => 'MUN ', /* Mundari */ + 'ur' => 'URD ', /* Urdu */ + 'uz' => 'UZB ', /* Uzbek */ + 've' => 'VEN ', /* Venda */ + 'vi' => 'VIT ', /* Vietnamese */ + 'vmw' => 'MAK ', /* Makua */ + 'wbm' => 'WA ', /* Wa */ + 'wbr' => 'WAG ', /* Wagdi */ + 'wo' => 'WLF ', /* Wolof */ + 'xal' => 'KLM ', /* Kalmyk */ + 'xh' => 'XHS ', /* Xhosa */ + 'xom' => 'KMO ', /* Komo (Sudan) */ + 'xsl' => 'SSL ', /* South Slavey */ + 'yi' => 'JII ', /* Yiddish */ + 'yid' => 'JII ', /* Yiddish */ + 'yo' => 'YBA ', /* Yoruba */ + 'yso' => 'NIS ', /* Nisi (China) */ + 'zne' => 'ZND ', /* Zande */ + 'zu' => 'ZUL ', /* Zulu */ + 'zh-cn' => 'ZHS ', /* Chinese (China) */ + 'zh-hk' => 'ZHH ', /* Chinese (Hong Kong) */ + 'zh-mo' => 'ZHT ', /* Chinese (Macao) */ + 'zh-sg' => 'ZHS ', /* Chinese (Singapore) */ + 'zh-tw' => 'ZHT ', /* Chinese (Taiwan) */ + ]; + + // hb-unicode.h + const UNICODE_GENERAL_CATEGORY_CONTROL = 0; /* Cc */ + const UNICODE_GENERAL_CATEGORY_FORMAT = 1; /* Cf */ + const UNICODE_GENERAL_CATEGORY_UNASSIGNED = 2; /* Cn */ + const UNICODE_GENERAL_CATEGORY_PRIVATE_USE = 3; /* Co */ + const UNICODE_GENERAL_CATEGORY_SURROGATE = 4; /* Cs */ + const UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER = 5; /* Ll */ + const UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER = 6; /* Lm */ + const UNICODE_GENERAL_CATEGORY_OTHER_LETTER = 7; /* Lo */ + const UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER = 8; /* Lt */ + const UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER = 9; /* Lu */ + const UNICODE_GENERAL_CATEGORY_SPACING_MARK = 10; /* Mc */ + const UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK = 11; /* Me */ + const UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK = 12; /* Mn */ + const UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER = 13; /* Nd */ + const UNICODE_GENERAL_CATEGORY_LETTER_NUMBER = 14; /* Nl */ + const UNICODE_GENERAL_CATEGORY_OTHER_NUMBER = 15; /* No */ + const UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION = 16; /* Pc */ + const UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION = 17; /* Pd */ + const UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION = 18; /* Pe */ + const UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION = 19; /* Pf */ + const UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION = 20; /* Pi */ + const UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION = 21; /* Po */ + const UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION = 22; /* Ps */ + const UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL = 23; /* Sc */ + const UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL = 24; /* Sk */ + const UNICODE_GENERAL_CATEGORY_MATH_SYMBOL = 25; /* Sm */ + const UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL = 26; /* So */ + const UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR = 27; /* Zl */ + const UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR = 28; /* Zp */ + const UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR = 29; /* Zs */ + + function general_category_is_mark($gen_cat) + { + return $gen_cat == self::UNICODE_GENERAL_CATEGORY_SPACING_MARK || $gen_cat == self::UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK || + $gen_cat == self::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK; + // define UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) + //if (FLAG(gen_cat) & (FLAG(UNICODE_GENERAL_CATEGORY_SPACING_MARK) | FLAG(UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) { return true; } + } + + const BIDI_CLASS_L = 0; + const BIDI_CLASS_LRE = 1; + const BIDI_CLASS_LRO = 2; + const BIDI_CLASS_R = 3; + const BIDI_CLASS_AL = 4; + const BIDI_CLASS_RLE = 5; + const BIDI_CLASS_RLO = 6; + const BIDI_CLASS_PDF = 7; + const BIDI_CLASS_EN = 8; + const BIDI_CLASS_ES = 9; + const BIDI_CLASS_ET = 10; + const BIDI_CLASS_AN = 11; + const BIDI_CLASS_CS = 12; + const BIDI_CLASS_NSM = 13; + const BIDI_CLASS_BN = 14; + const BIDI_CLASS_B = 15; + const BIDI_CLASS_S = 16; + const BIDI_CLASS_WS = 17; + const BIDI_CLASS_ON = 18; + + // UNIDATA_VERSION 6.2.0 + /* a list of unique database records */ + /* struct { + category; + combining; + bidi_class; + mirrored; + east_asian_width; + normalization_check; + script; + } + */ + private static $ucd_records = [ + [2, 0, 18, 0, 5, 0, 102], + [0, 0, 14, 0, 5, 0, 0], + [0, 0, 16, 0, 5, 0, 0], + [0, 0, 15, 0, 5, 0, 0], + [0, 0, 17, 0, 5, 0, 0], + [29, 0, 17, 0, 3, 0, 0], + [21, 0, 18, 0, 3, 0, 0], + [21, 0, 10, 0, 3, 0, 0], + [23, 0, 10, 0, 3, 0, 0], + [22, 0, 18, 1, 3, 0, 0], + [18, 0, 18, 1, 3, 0, 0], + [25, 0, 9, 0, 3, 0, 0], + [21, 0, 12, 0, 3, 0, 0], + [17, 0, 9, 0, 3, 0, 0], + [13, 0, 8, 0, 3, 0, 0], + [25, 0, 18, 1, 3, 0, 0], + [25, 0, 18, 0, 3, 0, 0], + [9, 0, 0, 0, 3, 0, 1], + [24, 0, 18, 0, 3, 0, 0], + [16, 0, 18, 0, 3, 0, 0], + [5, 0, 0, 0, 3, 0, 1], + [29, 0, 12, 0, 5, 0, 0], + [21, 0, 18, 0, 4, 0, 0], + [23, 0, 10, 0, 4, 0, 0], + [26, 0, 18, 0, 3, 0, 0], + [24, 0, 18, 0, 4, 0, 0], + [26, 0, 18, 0, 5, 0, 0], + [7, 0, 0, 0, 4, 0, 1], + [20, 0, 18, 1, 5, 0, 0], + [1, 0, 14, 0, 4, 0, 0], + [26, 0, 18, 0, 4, 0, 0], + [26, 0, 10, 0, 4, 0, 0], + [25, 0, 10, 0, 4, 0, 0], + [15, 0, 8, 0, 4, 0, 0], + [5, 0, 0, 0, 5, 0, 0], + [19, 0, 18, 1, 5, 0, 0], + [15, 0, 18, 0, 4, 0, 0], + [9, 0, 0, 0, 5, 0, 1], + [9, 0, 0, 0, 4, 0, 1], + [25, 0, 18, 0, 4, 0, 0], + [5, 0, 0, 0, 4, 0, 1], + [5, 0, 0, 0, 5, 0, 1], + [7, 0, 0, 0, 5, 0, 1], + [8, 0, 0, 0, 5, 0, 1], + [6, 0, 0, 0, 5, 0, 1], + [6, 0, 18, 0, 5, 0, 0], + [6, 0, 0, 0, 5, 0, 0], + [24, 0, 18, 0, 5, 0, 0], + [6, 0, 18, 0, 4, 0, 0], + [6, 0, 0, 0, 4, 0, 0], + [24, 0, 18, 0, 5, 0, 34], + [12, 230, 13, 0, 4, 0, 40], + [12, 232, 13, 0, 4, 0, 40], + [12, 220, 13, 0, 4, 0, 40], + [12, 216, 13, 0, 4, 0, 40], + [12, 202, 13, 0, 4, 0, 40], + [12, 1, 13, 0, 4, 0, 40], + [12, 240, 13, 0, 4, 0, 40], + [12, 0, 13, 0, 4, 0, 40], + [12, 233, 13, 0, 4, 0, 40], + [12, 234, 13, 0, 4, 0, 40], + [9, 0, 0, 0, 5, 0, 2], + [5, 0, 0, 0, 5, 0, 2], + [24, 0, 18, 0, 5, 0, 2], + [2, 0, 18, 0, 5, 0, 102], + [6, 0, 0, 0, 5, 0, 2], + [21, 0, 18, 0, 5, 0, 0], + [9, 0, 0, 0, 4, 0, 2], + [5, 0, 0, 0, 4, 0, 2], + [9, 0, 0, 0, 5, 0, 54], + [5, 0, 0, 0, 5, 0, 54], + [25, 0, 18, 0, 5, 0, 2], + [9, 0, 0, 0, 5, 0, 3], + [9, 0, 0, 0, 4, 0, 3], + [5, 0, 0, 0, 4, 0, 3], + [5, 0, 0, 0, 5, 0, 3], + [26, 0, 0, 0, 5, 0, 3], + [12, 230, 13, 0, 5, 0, 3], + [12, 230, 13, 0, 5, 0, 40], + [11, 0, 13, 0, 5, 0, 3], + [9, 0, 0, 0, 5, 0, 4], + [6, 0, 0, 0, 5, 0, 4], + [21, 0, 0, 0, 5, 0, 4], + [5, 0, 0, 0, 5, 0, 4], + [21, 0, 0, 0, 5, 0, 0], + [17, 0, 18, 0, 5, 0, 4], + [23, 0, 10, 0, 5, 0, 4], + [12, 220, 13, 0, 5, 0, 5], + [12, 230, 13, 0, 5, 0, 5], + [12, 222, 13, 0, 5, 0, 5], + [12, 228, 13, 0, 5, 0, 5], + [12, 10, 13, 0, 5, 0, 5], + [12, 11, 13, 0, 5, 0, 5], + [12, 12, 13, 0, 5, 0, 5], + [12, 13, 13, 0, 5, 0, 5], + [12, 14, 13, 0, 5, 0, 5], + [12, 15, 13, 0, 5, 0, 5], + [12, 16, 13, 0, 5, 0, 5], + [12, 17, 13, 0, 5, 0, 5], + [12, 18, 13, 0, 5, 0, 5], + [12, 19, 13, 0, 5, 0, 5], + [12, 20, 13, 0, 5, 0, 5], + [12, 21, 13, 0, 5, 0, 5], + [12, 22, 13, 0, 5, 0, 5], + [17, 0, 3, 0, 5, 0, 5], + [12, 23, 13, 0, 5, 0, 5], + [21, 0, 3, 0, 5, 0, 5], + [12, 24, 13, 0, 5, 0, 5], + [12, 25, 13, 0, 5, 0, 5], + [7, 0, 3, 0, 5, 0, 5], + [1, 0, 11, 0, 5, 0, 6], + [25, 0, 18, 0, 5, 0, 6], + [25, 0, 4, 0, 5, 0, 6], + [21, 0, 10, 0, 5, 0, 6], + [23, 0, 4, 0, 5, 0, 6], + [21, 0, 12, 0, 5, 0, 0], + [21, 0, 4, 0, 5, 0, 6], + [26, 0, 18, 0, 5, 0, 6], + [12, 230, 13, 0, 5, 0, 6], + [12, 30, 13, 0, 5, 0, 6], + [12, 31, 13, 0, 5, 0, 6], + [12, 32, 13, 0, 5, 0, 6], + [21, 0, 4, 0, 5, 0, 0], + [7, 0, 4, 0, 5, 0, 6], + [6, 0, 4, 0, 5, 0, 0], + [12, 27, 13, 0, 5, 0, 40], + [12, 28, 13, 0, 5, 0, 40], + [12, 29, 13, 0, 5, 0, 40], + [12, 30, 13, 0, 5, 0, 40], + [12, 31, 13, 0, 5, 0, 40], + [12, 32, 13, 0, 5, 0, 40], + [12, 33, 13, 0, 5, 0, 40], + [12, 34, 13, 0, 5, 0, 40], + [12, 220, 13, 0, 5, 0, 40], + [12, 220, 13, 0, 5, 0, 6], + [13, 0, 11, 0, 5, 0, 0], + [21, 0, 11, 0, 5, 0, 6], + [12, 35, 13, 0, 5, 0, 40], + [1, 0, 11, 0, 5, 0, 0], + [6, 0, 4, 0, 5, 0, 6], + [13, 0, 8, 0, 5, 0, 6], + [26, 0, 4, 0, 5, 0, 6], + [21, 0, 4, 0, 5, 0, 7], + [1, 0, 4, 0, 5, 0, 7], + [7, 0, 4, 0, 5, 0, 7], + [12, 36, 13, 0, 5, 0, 7], + [12, 230, 13, 0, 5, 0, 7], + [12, 220, 13, 0, 5, 0, 7], + [7, 0, 4, 0, 5, 0, 8], + [12, 0, 13, 0, 5, 0, 8], + [13, 0, 3, 0, 5, 0, 65], + [7, 0, 3, 0, 5, 0, 65], + [12, 230, 13, 0, 5, 0, 65], + [12, 220, 13, 0, 5, 0, 65], + [6, 0, 3, 0, 5, 0, 65], + [26, 0, 18, 0, 5, 0, 65], + [21, 0, 18, 0, 5, 0, 65], + [7, 0, 3, 0, 5, 0, 81], + [12, 230, 13, 0, 5, 0, 81], + [6, 0, 3, 0, 5, 0, 81], + [21, 0, 3, 0, 5, 0, 81], + [7, 0, 3, 0, 5, 0, 94], + [12, 220, 13, 0, 5, 0, 94], + [21, 0, 3, 0, 5, 0, 94], + [12, 27, 13, 0, 5, 0, 6], + [12, 28, 13, 0, 5, 0, 6], + [12, 29, 13, 0, 5, 0, 6], + [12, 0, 13, 0, 5, 0, 9], + [10, 0, 0, 0, 5, 0, 9], + [7, 0, 0, 0, 5, 0, 9], + [12, 7, 13, 0, 5, 0, 9], + [12, 9, 13, 0, 5, 0, 9], + [12, 230, 13, 0, 5, 0, 9], + [13, 0, 0, 0, 5, 0, 9], + [21, 0, 0, 0, 5, 0, 9], + [6, 0, 0, 0, 5, 0, 9], + [12, 0, 13, 0, 5, 0, 10], + [10, 0, 0, 0, 5, 0, 10], + [7, 0, 0, 0, 5, 0, 10], + [12, 7, 13, 0, 5, 0, 10], + [12, 9, 13, 0, 5, 0, 10], + [13, 0, 0, 0, 5, 0, 10], + [23, 0, 10, 0, 5, 0, 10], + [15, 0, 0, 0, 5, 0, 10], + [26, 0, 0, 0, 5, 0, 10], + [12, 0, 13, 0, 5, 0, 11], + [10, 0, 0, 0, 5, 0, 11], + [7, 0, 0, 0, 5, 0, 11], + [12, 7, 13, 0, 5, 0, 11], + [12, 9, 13, 0, 5, 0, 11], + [13, 0, 0, 0, 5, 0, 11], + [12, 0, 13, 0, 5, 0, 12], + [10, 0, 0, 0, 5, 0, 12], + [7, 0, 0, 0, 5, 0, 12], + [12, 7, 13, 0, 5, 0, 12], + [12, 9, 13, 0, 5, 0, 12], + [13, 0, 0, 0, 5, 0, 12], + [21, 0, 0, 0, 5, 0, 12], + [23, 0, 10, 0, 5, 0, 12], + [12, 0, 13, 0, 5, 0, 13], + [10, 0, 0, 0, 5, 0, 13], + [7, 0, 0, 0, 5, 0, 13], + [12, 7, 13, 0, 5, 0, 13], + [12, 9, 13, 0, 5, 0, 13], + [13, 0, 0, 0, 5, 0, 13], + [26, 0, 0, 0, 5, 0, 13], + [15, 0, 0, 0, 5, 0, 13], + [12, 0, 13, 0, 5, 0, 14], + [7, 0, 0, 0, 5, 0, 14], + [10, 0, 0, 0, 5, 0, 14], + [12, 9, 13, 0, 5, 0, 14], + [13, 0, 0, 0, 5, 0, 14], + [15, 0, 0, 0, 5, 0, 14], + [26, 0, 18, 0, 5, 0, 14], + [23, 0, 10, 0, 5, 0, 14], + [10, 0, 0, 0, 5, 0, 15], + [7, 0, 0, 0, 5, 0, 15], + [12, 0, 13, 0, 5, 0, 15], + [12, 9, 13, 0, 5, 0, 15], + [12, 84, 13, 0, 5, 0, 15], + [12, 91, 13, 0, 5, 0, 15], + [13, 0, 0, 0, 5, 0, 15], + [15, 0, 18, 0, 5, 0, 15], + [26, 0, 0, 0, 5, 0, 15], + [10, 0, 0, 0, 5, 0, 16], + [7, 0, 0, 0, 5, 0, 16], + [12, 7, 13, 0, 5, 0, 16], + [12, 0, 0, 0, 5, 0, 16], + [12, 0, 13, 0, 5, 0, 16], + [12, 9, 13, 0, 5, 0, 16], + [13, 0, 0, 0, 5, 0, 16], + [10, 0, 0, 0, 5, 0, 17], + [7, 0, 0, 0, 5, 0, 17], + [12, 0, 13, 0, 5, 0, 17], + [12, 9, 13, 0, 5, 0, 17], + [13, 0, 0, 0, 5, 0, 17], + [15, 0, 0, 0, 5, 0, 17], + [26, 0, 0, 0, 5, 0, 17], + [10, 0, 0, 0, 5, 0, 18], + [7, 0, 0, 0, 5, 0, 18], + [12, 9, 13, 0, 5, 0, 18], + [12, 0, 13, 0, 5, 0, 18], + [21, 0, 0, 0, 5, 0, 18], + [7, 0, 0, 0, 5, 0, 19], + [12, 0, 13, 0, 5, 0, 19], + [12, 103, 13, 0, 5, 0, 19], + [12, 9, 13, 0, 5, 0, 19], + [23, 0, 10, 0, 5, 0, 0], + [6, 0, 0, 0, 5, 0, 19], + [12, 107, 13, 0, 5, 0, 19], + [21, 0, 0, 0, 5, 0, 19], + [13, 0, 0, 0, 5, 0, 19], + [7, 0, 0, 0, 5, 0, 20], + [12, 0, 13, 0, 5, 0, 20], + [12, 118, 13, 0, 5, 0, 20], + [6, 0, 0, 0, 5, 0, 20], + [12, 122, 13, 0, 5, 0, 20], + [13, 0, 0, 0, 5, 0, 20], + [7, 0, 0, 0, 5, 0, 21], + [26, 0, 0, 0, 5, 0, 21], + [21, 0, 0, 0, 5, 0, 21], + [12, 220, 13, 0, 5, 0, 21], + [13, 0, 0, 0, 5, 0, 21], + [15, 0, 0, 0, 5, 0, 21], + [12, 216, 13, 0, 5, 0, 21], + [22, 0, 18, 1, 5, 0, 21], + [18, 0, 18, 1, 5, 0, 21], + [10, 0, 0, 0, 5, 0, 21], + [12, 129, 13, 0, 5, 0, 21], + [12, 130, 13, 0, 5, 0, 21], + [12, 0, 13, 0, 5, 0, 21], + [12, 132, 13, 0, 5, 0, 21], + [12, 230, 13, 0, 5, 0, 21], + [12, 9, 13, 0, 5, 0, 21], + [26, 0, 0, 0, 5, 0, 0], + [7, 0, 0, 0, 5, 0, 22], + [10, 0, 0, 0, 5, 0, 22], + [12, 0, 13, 0, 5, 0, 22], + [12, 7, 13, 0, 5, 0, 22], + [12, 9, 13, 0, 5, 0, 22], + [13, 0, 0, 0, 5, 0, 22], + [21, 0, 0, 0, 5, 0, 22], + [12, 220, 13, 0, 5, 0, 22], + [26, 0, 0, 0, 5, 0, 22], + [9, 0, 0, 0, 5, 0, 23], + [7, 0, 0, 0, 5, 0, 23], + [6, 0, 0, 0, 5, 0, 23], + [7, 0, 0, 0, 2, 0, 24], + [7, 0, 0, 0, 5, 0, 24], + [7, 0, 0, 0, 5, 0, 25], + [12, 230, 13, 0, 5, 0, 25], + [21, 0, 0, 0, 5, 0, 25], + [15, 0, 0, 0, 5, 0, 25], + [26, 0, 18, 0, 5, 0, 25], + [7, 0, 0, 0, 5, 0, 26], + [17, 0, 18, 0, 5, 0, 27], + [7, 0, 0, 0, 5, 0, 27], + [21, 0, 0, 0, 5, 0, 27], + [29, 0, 17, 0, 5, 0, 28], + [7, 0, 0, 0, 5, 0, 28], + [22, 0, 18, 1, 5, 0, 28], + [18, 0, 18, 1, 5, 0, 28], + [7, 0, 0, 0, 5, 0, 29], + [14, 0, 0, 0, 5, 0, 29], + [7, 0, 0, 0, 5, 0, 41], + [12, 0, 13, 0, 5, 0, 41], + [12, 9, 13, 0, 5, 0, 41], + [7, 0, 0, 0, 5, 0, 42], + [12, 0, 13, 0, 5, 0, 42], + [12, 9, 13, 0, 5, 0, 42], + [7, 0, 0, 0, 5, 0, 43], + [12, 0, 13, 0, 5, 0, 43], + [7, 0, 0, 0, 5, 0, 44], + [12, 0, 13, 0, 5, 0, 44], + [7, 0, 0, 0, 5, 0, 30], + [12, 0, 13, 0, 5, 0, 30], + [10, 0, 0, 0, 5, 0, 30], + [12, 9, 13, 0, 5, 0, 30], + [21, 0, 0, 0, 5, 0, 30], + [6, 0, 0, 0, 5, 0, 30], + [23, 0, 10, 0, 5, 0, 30], + [12, 230, 13, 0, 5, 0, 30], + [13, 0, 0, 0, 5, 0, 30], + [15, 0, 18, 0, 5, 0, 30], + [21, 0, 18, 0, 5, 0, 31], + [17, 0, 18, 0, 5, 0, 31], + [12, 0, 13, 0, 5, 0, 31], + [29, 0, 17, 0, 5, 0, 31], + [13, 0, 0, 0, 5, 0, 31], + [7, 0, 0, 0, 5, 0, 31], + [6, 0, 0, 0, 5, 0, 31], + [12, 228, 13, 0, 5, 0, 31], + [7, 0, 0, 0, 5, 0, 45], + [12, 0, 13, 0, 5, 0, 45], + [10, 0, 0, 0, 5, 0, 45], + [12, 222, 13, 0, 5, 0, 45], + [12, 230, 13, 0, 5, 0, 45], + [12, 220, 13, 0, 5, 0, 45], + [26, 0, 18, 0, 5, 0, 45], + [21, 0, 18, 0, 5, 0, 45], + [13, 0, 0, 0, 5, 0, 45], + [7, 0, 0, 0, 5, 0, 46], + [7, 0, 0, 0, 5, 0, 55], + [10, 0, 0, 0, 5, 0, 55], + [13, 0, 0, 0, 5, 0, 55], + [15, 0, 0, 0, 5, 0, 55], + [26, 0, 18, 0, 5, 0, 55], + [26, 0, 18, 0, 5, 0, 30], + [7, 0, 0, 0, 5, 0, 53], + [12, 230, 13, 0, 5, 0, 53], + [12, 220, 13, 0, 5, 0, 53], + [10, 0, 0, 0, 5, 0, 53], + [21, 0, 0, 0, 5, 0, 53], + [7, 0, 0, 0, 5, 0, 77], + [10, 0, 0, 0, 5, 0, 77], + [12, 0, 13, 0, 5, 0, 77], + [12, 9, 13, 0, 5, 0, 77], + [12, 230, 13, 0, 5, 0, 77], + [12, 220, 13, 0, 5, 0, 77], + [13, 0, 0, 0, 5, 0, 77], + [21, 0, 0, 0, 5, 0, 77], + [6, 0, 0, 0, 5, 0, 77], + [12, 0, 13, 0, 5, 0, 61], + [10, 0, 0, 0, 5, 0, 61], + [7, 0, 0, 0, 5, 0, 61], + [12, 7, 13, 0, 5, 0, 61], + [10, 9, 0, 0, 5, 0, 61], + [13, 0, 0, 0, 5, 0, 61], + [21, 0, 0, 0, 5, 0, 61], + [26, 0, 0, 0, 5, 0, 61], + [12, 230, 13, 0, 5, 0, 61], + [12, 220, 13, 0, 5, 0, 61], + [12, 0, 13, 0, 5, 0, 66], + [10, 0, 0, 0, 5, 0, 66], + [7, 0, 0, 0, 5, 0, 66], + [10, 9, 0, 0, 5, 0, 66], + [12, 9, 13, 0, 5, 0, 66], + [13, 0, 0, 0, 5, 0, 66], + [7, 0, 0, 0, 5, 0, 92], + [12, 7, 13, 0, 5, 0, 92], + [10, 0, 0, 0, 5, 0, 92], + [12, 0, 13, 0, 5, 0, 92], + [10, 9, 0, 0, 5, 0, 92], + [21, 0, 0, 0, 5, 0, 92], + [7, 0, 0, 0, 5, 0, 67], + [10, 0, 0, 0, 5, 0, 67], + [12, 0, 13, 0, 5, 0, 67], + [12, 7, 13, 0, 5, 0, 67], + [21, 0, 0, 0, 5, 0, 67], + [13, 0, 0, 0, 5, 0, 67], + [13, 0, 0, 0, 5, 0, 68], + [7, 0, 0, 0, 5, 0, 68], + [6, 0, 0, 0, 5, 0, 68], + [21, 0, 0, 0, 5, 0, 68], + [21, 0, 0, 0, 5, 0, 66], + [12, 1, 13, 0, 5, 0, 40], + [10, 0, 0, 0, 5, 0, 0], + [7, 0, 0, 0, 5, 0, 0], + [6, 0, 0, 0, 5, 0, 3], + [12, 234, 13, 0, 5, 0, 40], + [12, 214, 13, 0, 5, 0, 40], + [12, 202, 13, 0, 5, 0, 40], + [12, 233, 13, 0, 5, 0, 40], + [8, 0, 0, 0, 5, 0, 2], + [29, 0, 17, 0, 5, 0, 0], + [1, 0, 14, 0, 5, 0, 0], + [1, 0, 14, 0, 5, 0, 40], + [1, 0, 0, 0, 5, 0, 0], + [1, 0, 3, 0, 5, 0, 0], + [17, 0, 18, 0, 4, 0, 0], + [17, 0, 18, 0, 5, 0, 0], + [20, 0, 18, 0, 4, 0, 0], + [19, 0, 18, 0, 4, 0, 0], + [22, 0, 18, 0, 5, 0, 0], + [20, 0, 18, 0, 5, 0, 0], + [27, 0, 17, 0, 5, 0, 0], + [28, 0, 15, 0, 5, 0, 0], + [1, 0, 1, 0, 5, 0, 0], + [1, 0, 5, 0, 5, 0, 0], + [1, 0, 7, 0, 5, 0, 0], + [1, 0, 2, 0, 5, 0, 0], + [1, 0, 6, 0, 5, 0, 0], + [21, 0, 10, 0, 4, 0, 0], + [21, 0, 10, 0, 5, 0, 0], + [16, 0, 18, 0, 5, 0, 0], + [25, 0, 12, 0, 5, 0, 0], + [22, 0, 18, 1, 5, 0, 0], + [18, 0, 18, 1, 5, 0, 0], + [25, 0, 18, 0, 5, 0, 0], + [15, 0, 8, 0, 5, 0, 0], + [25, 0, 9, 0, 5, 0, 0], + [6, 0, 0, 0, 4, 0, 1], + [23, 0, 10, 0, 1, 0, 0], + [11, 0, 13, 0, 5, 0, 40], + [9, 0, 0, 0, 5, 0, 0], + [5, 0, 0, 0, 4, 0, 0], + [26, 0, 10, 0, 5, 0, 0], + [25, 0, 18, 1, 5, 0, 0], + [15, 0, 18, 0, 5, 0, 0], + [14, 0, 0, 0, 4, 0, 1], + [14, 0, 0, 0, 5, 0, 1], + [25, 0, 18, 1, 4, 0, 0], + [25, 0, 10, 0, 5, 0, 0], + [22, 0, 18, 1, 2, 0, 0], + [18, 0, 18, 1, 2, 0, 0], + [26, 0, 0, 0, 4, 0, 0], + [26, 0, 0, 0, 5, 0, 52], + [9, 0, 0, 0, 5, 0, 56], + [5, 0, 0, 0, 5, 0, 56], + [26, 0, 18, 0, 5, 0, 54], + [12, 230, 13, 0, 5, 0, 54], + [21, 0, 18, 0, 5, 0, 54], + [15, 0, 18, 0, 5, 0, 54], + [5, 0, 0, 0, 5, 0, 23], + [7, 0, 0, 0, 5, 0, 57], + [6, 0, 0, 0, 5, 0, 57], + [21, 0, 0, 0, 5, 0, 57], + [12, 9, 13, 0, 5, 0, 57], + [26, 0, 18, 0, 2, 0, 35], + [26, 0, 18, 0, 2, 0, 0], + [29, 0, 17, 0, 0, 0, 0], + [21, 0, 18, 0, 2, 0, 0], + [6, 0, 0, 0, 2, 0, 35], + [7, 0, 0, 0, 2, 0, 0], + [14, 0, 0, 0, 2, 0, 35], + [17, 0, 18, 0, 2, 0, 0], + [22, 0, 18, 0, 2, 0, 0], + [18, 0, 18, 0, 2, 0, 0], + [12, 218, 13, 0, 2, 0, 40], + [12, 228, 13, 0, 2, 0, 40], + [12, 232, 13, 0, 2, 0, 40], + [12, 222, 13, 0, 2, 0, 40], + [10, 224, 0, 0, 2, 0, 24], + [6, 0, 0, 0, 2, 0, 0], + [7, 0, 0, 0, 2, 0, 32], + [12, 8, 13, 0, 2, 0, 40], + [24, 0, 18, 0, 2, 0, 0], + [6, 0, 0, 0, 2, 0, 32], + [7, 0, 0, 0, 2, 0, 33], + [6, 0, 0, 0, 2, 0, 33], + [7, 0, 0, 0, 2, 0, 34], + [26, 0, 0, 0, 2, 0, 0], + [15, 0, 0, 0, 2, 0, 0], + [26, 0, 0, 0, 2, 0, 24], + [26, 0, 18, 0, 2, 0, 24], + [15, 0, 0, 0, 4, 0, 0], + [15, 0, 18, 0, 2, 0, 0], + [26, 0, 0, 0, 2, 0, 33], + [7, 0, 0, 0, 2, 0, 35], + [2, 0, 18, 0, 2, 0, 35], + [2, 0, 18, 0, 2, 0, 102], + [7, 0, 0, 0, 2, 0, 36], + [6, 0, 0, 0, 2, 0, 36], + [26, 0, 18, 0, 2, 0, 36], + [7, 0, 0, 0, 5, 0, 82], + [6, 0, 0, 0, 5, 0, 82], + [21, 0, 0, 0, 5, 0, 82], + [7, 0, 0, 0, 5, 0, 69], + [6, 0, 0, 0, 5, 0, 69], + [21, 0, 18, 0, 5, 0, 69], + [13, 0, 0, 0, 5, 0, 69], + [7, 0, 0, 0, 5, 0, 3], + [21, 0, 18, 0, 5, 0, 3], + [6, 0, 18, 0, 5, 0, 3], + [7, 0, 0, 0, 5, 0, 83], + [14, 0, 0, 0, 5, 0, 83], + [12, 230, 13, 0, 5, 0, 83], + [21, 0, 0, 0, 5, 0, 83], + [24, 0, 0, 0, 5, 0, 0], + [7, 0, 0, 0, 5, 0, 58], + [12, 0, 13, 0, 5, 0, 58], + [12, 9, 13, 0, 5, 0, 58], + [10, 0, 0, 0, 5, 0, 58], + [26, 0, 18, 0, 5, 0, 58], + [15, 0, 0, 0, 5, 0, 0], + [7, 0, 0, 0, 5, 0, 64], + [21, 0, 18, 0, 5, 0, 64], + [10, 0, 0, 0, 5, 0, 70], + [7, 0, 0, 0, 5, 0, 70], + [12, 9, 13, 0, 5, 0, 70], + [21, 0, 0, 0, 5, 0, 70], + [13, 0, 0, 0, 5, 0, 70], + [13, 0, 0, 0, 5, 0, 71], + [7, 0, 0, 0, 5, 0, 71], + [12, 0, 13, 0, 5, 0, 71], + [12, 220, 13, 0, 5, 0, 71], + [21, 0, 0, 0, 5, 0, 71], + [7, 0, 0, 0, 5, 0, 72], + [12, 0, 13, 0, 5, 0, 72], + [10, 0, 0, 0, 5, 0, 72], + [10, 9, 0, 0, 5, 0, 72], + [21, 0, 0, 0, 5, 0, 72], + [12, 0, 13, 0, 5, 0, 84], + [10, 0, 0, 0, 5, 0, 84], + [7, 0, 0, 0, 5, 0, 84], + [12, 7, 13, 0, 5, 0, 84], + [10, 9, 0, 0, 5, 0, 84], + [21, 0, 0, 0, 5, 0, 84], + [6, 0, 0, 0, 5, 0, 84], + [13, 0, 0, 0, 5, 0, 84], + [7, 0, 0, 0, 5, 0, 76], + [12, 0, 13, 0, 5, 0, 76], + [10, 0, 0, 0, 5, 0, 76], + [13, 0, 0, 0, 5, 0, 76], + [21, 0, 0, 0, 5, 0, 76], + [6, 0, 0, 0, 5, 0, 22], + [7, 0, 0, 0, 5, 0, 78], + [12, 230, 13, 0, 5, 0, 78], + [12, 220, 13, 0, 5, 0, 78], + [6, 0, 0, 0, 5, 0, 78], + [21, 0, 0, 0, 5, 0, 78], + [7, 0, 0, 0, 5, 0, 85], + [10, 0, 0, 0, 5, 0, 85], + [12, 0, 13, 0, 5, 0, 85], + [21, 0, 0, 0, 5, 0, 85], + [6, 0, 0, 0, 5, 0, 85], + [12, 9, 13, 0, 5, 0, 85], + [13, 0, 0, 0, 5, 0, 85], + [2, 0, 18, 0, 2, 0, 24], + [4, 0, 0, 0, 5, 0, 102], + [3, 0, 0, 0, 4, 0, 102], + [2, 0, 18, 0, 4, 0, 102], + [12, 26, 13, 0, 5, 0, 5], + [25, 0, 9, 0, 5, 0, 5], + [24, 0, 4, 0, 5, 0, 6], + [18, 0, 18, 0, 5, 0, 0], + [16, 0, 18, 0, 2, 0, 0], + [21, 0, 12, 0, 2, 0, 0], + [21, 0, 10, 0, 2, 0, 0], + [25, 0, 9, 0, 2, 0, 0], + [17, 0, 9, 0, 2, 0, 0], + [25, 0, 18, 1, 2, 0, 0], + [25, 0, 18, 0, 2, 0, 0], + [23, 0, 10, 0, 2, 0, 0], + [21, 0, 18, 0, 0, 0, 0], + [21, 0, 10, 0, 0, 0, 0], + [23, 0, 10, 0, 0, 0, 0], + [22, 0, 18, 1, 0, 0, 0], + [18, 0, 18, 1, 0, 0, 0], + [25, 0, 9, 0, 0, 0, 0], + [21, 0, 12, 0, 0, 0, 0], + [17, 0, 9, 0, 0, 0, 0], + [13, 0, 8, 0, 0, 0, 0], + [25, 0, 18, 1, 0, 0, 0], + [25, 0, 18, 0, 0, 0, 0], + [9, 0, 0, 0, 0, 0, 1], + [24, 0, 18, 0, 0, 0, 0], + [16, 0, 18, 0, 0, 0, 0], + [5, 0, 0, 0, 0, 0, 1], + [21, 0, 18, 0, 1, 0, 0], + [22, 0, 18, 1, 1, 0, 0], + [18, 0, 18, 1, 1, 0, 0], + [7, 0, 0, 0, 1, 0, 33], + [6, 0, 0, 0, 1, 0, 0], + [7, 0, 0, 0, 1, 0, 24], + [26, 0, 18, 0, 0, 0, 0], + [26, 0, 18, 0, 1, 0, 0], + [25, 0, 18, 0, 1, 0, 0], + [1, 0, 18, 0, 5, 0, 0], + [7, 0, 0, 0, 5, 0, 47], + [14, 0, 18, 0, 5, 0, 2], + [15, 0, 18, 0, 5, 0, 2], + [26, 0, 18, 0, 5, 0, 2], + [7, 0, 0, 0, 5, 0, 73], + [7, 0, 0, 0, 5, 0, 74], + [7, 0, 0, 0, 5, 0, 37], + [15, 0, 0, 0, 5, 0, 37], + [7, 0, 0, 0, 5, 0, 38], + [14, 0, 0, 0, 5, 0, 38], + [7, 0, 0, 0, 5, 0, 48], + [21, 0, 0, 0, 5, 0, 48], + [7, 0, 0, 0, 5, 0, 59], + [21, 0, 0, 0, 5, 0, 59], + [14, 0, 0, 0, 5, 0, 59], + [9, 0, 0, 0, 5, 0, 39], + [5, 0, 0, 0, 5, 0, 39], + [7, 0, 0, 0, 5, 0, 49], + [7, 0, 0, 0, 5, 0, 50], + [13, 0, 0, 0, 5, 0, 50], + [7, 0, 3, 0, 5, 0, 51], + [7, 0, 3, 0, 5, 0, 86], + [21, 0, 3, 0, 5, 0, 86], + [15, 0, 3, 0, 5, 0, 86], + [7, 0, 3, 0, 5, 0, 63], + [15, 0, 3, 0, 5, 0, 63], + [21, 0, 18, 0, 5, 0, 63], + [7, 0, 3, 0, 5, 0, 75], + [21, 0, 3, 0, 5, 0, 75], + [7, 0, 3, 0, 5, 0, 97], + [7, 0, 3, 0, 5, 0, 96], + [7, 0, 3, 0, 5, 0, 60], + [12, 0, 13, 0, 5, 0, 60], + [12, 220, 13, 0, 5, 0, 60], + [12, 230, 13, 0, 5, 0, 60], + [12, 1, 13, 0, 5, 0, 60], + [12, 9, 13, 0, 5, 0, 60], + [15, 0, 3, 0, 5, 0, 60], + [21, 0, 3, 0, 5, 0, 60], + [7, 0, 3, 0, 5, 0, 87], + [15, 0, 3, 0, 5, 0, 87], + [21, 0, 3, 0, 5, 0, 87], + [7, 0, 3, 0, 5, 0, 79], + [21, 0, 18, 0, 5, 0, 79], + [7, 0, 3, 0, 5, 0, 88], + [15, 0, 3, 0, 5, 0, 88], + [7, 0, 3, 0, 5, 0, 89], + [15, 0, 3, 0, 5, 0, 89], + [7, 0, 3, 0, 5, 0, 90], + [15, 0, 11, 0, 5, 0, 6], + [10, 0, 0, 0, 5, 0, 93], + [12, 0, 13, 0, 5, 0, 93], + [7, 0, 0, 0, 5, 0, 93], + [12, 9, 13, 0, 5, 0, 93], + [21, 0, 0, 0, 5, 0, 93], + [15, 0, 18, 0, 5, 0, 93], + [13, 0, 0, 0, 5, 0, 93], + [12, 0, 13, 0, 5, 0, 91], + [10, 0, 0, 0, 5, 0, 91], + [7, 0, 0, 0, 5, 0, 91], + [12, 9, 13, 0, 5, 0, 91], + [12, 7, 13, 0, 5, 0, 91], + [21, 0, 0, 0, 5, 0, 91], + [1, 0, 0, 0, 5, 0, 91], + [7, 0, 0, 0, 5, 0, 100], + [13, 0, 0, 0, 5, 0, 100], + [12, 230, 13, 0, 5, 0, 95], + [7, 0, 0, 0, 5, 0, 95], + [12, 0, 13, 0, 5, 0, 95], + [10, 0, 0, 0, 5, 0, 95], + [12, 9, 13, 0, 5, 0, 95], + [13, 0, 0, 0, 5, 0, 95], + [21, 0, 0, 0, 5, 0, 95], + [12, 0, 13, 0, 5, 0, 99], + [10, 0, 0, 0, 5, 0, 99], + [7, 0, 0, 0, 5, 0, 99], + [10, 9, 0, 0, 5, 0, 99], + [21, 0, 0, 0, 5, 0, 99], + [13, 0, 0, 0, 5, 0, 99], + [7, 0, 0, 0, 5, 0, 101], + [12, 0, 13, 0, 5, 0, 101], + [10, 0, 0, 0, 5, 0, 101], + [10, 9, 0, 0, 5, 0, 101], + [12, 7, 13, 0, 5, 0, 101], + [13, 0, 0, 0, 5, 0, 101], + [7, 0, 0, 0, 5, 0, 62], + [14, 0, 0, 0, 5, 0, 62], + [21, 0, 0, 0, 5, 0, 62], + [7, 0, 0, 0, 5, 0, 80], + [7, 0, 0, 0, 5, 0, 98], + [10, 0, 0, 0, 5, 0, 98], + [12, 0, 13, 0, 5, 0, 98], + [6, 0, 0, 0, 5, 0, 98], + [10, 216, 0, 0, 5, 0, 0], + [10, 226, 0, 0, 5, 0, 0], + [12, 230, 13, 0, 5, 0, 2], + [25, 0, 0, 0, 5, 0, 0], + [13, 0, 8, 0, 5, 0, 0], + [26, 0, 0, 0, 2, 0, 32], + ]; + + /* Mirror unicode characters. Bidirectional Algorithm, at http://www.unicode.org/unicode/reports/tr9/ */ + + public static $mirror_pairs = [ + 40 => 41, + 41 => 40, + 60 => 62, + 62 => 60, + 91 => 93, + 93 => 91, + 123 => 125, + 125 => 123, + 171 => 187, + 187 => 171, + 3898 => 3899, + 3899 => 3898, + 3900 => 3901, + 3901 => 3900, + 5787 => 5788, + 5788 => 5787, + 8249 => 8250, + 8250 => 8249, + 8261 => 8262, + 8262 => 8261, + 8317 => 8318, + 8318 => 8317, + 8333 => 8334, + 8334 => 8333, + 8712 => 8715, + 8713 => 8716, + 8714 => 8717, + 8715 => 8712, + 8716 => 8713, + 8717 => 8714, + 8725 => 10741, + 8764 => 8765, + 8765 => 8764, + 8771 => 8909, + 8786 => 8787, + 8787 => 8786, + 8788 => 8789, + 8789 => 8788, + 8804 => 8805, + 8805 => 8804, + 8806 => 8807, + 8807 => 8806, + 8808 => 8809, + 8809 => 8808, + 8810 => 8811, + 8811 => 8810, + 8814 => 8815, + 8815 => 8814, + 8816 => 8817, + 8817 => 8816, + 8818 => 8819, + 8819 => 8818, + 8820 => 8821, + 8821 => 8820, + 8822 => 8823, + 8823 => 8822, + 8824 => 8825, + 8825 => 8824, + 8826 => 8827, + 8827 => 8826, + 8828 => 8829, + 8829 => 8828, + 8830 => 8831, + 8831 => 8830, + 8832 => 8833, + 8833 => 8832, + 8834 => 8835, + 8835 => 8834, + 8836 => 8837, + 8837 => 8836, + 8838 => 8839, + 8839 => 8838, + 8840 => 8841, + 8841 => 8840, + 8842 => 8843, + 8843 => 8842, + 8847 => 8848, + 8848 => 8847, + 8849 => 8850, + 8850 => 8849, + 8856 => 10680, + 8866 => 8867, + 8867 => 8866, + 8870 => 10974, + 8872 => 10980, + 8873 => 10979, + 8875 => 10981, + 8880 => 8881, + 8881 => 8880, + 8882 => 8883, + 8883 => 8882, + 8884 => 8885, + 8885 => 8884, + 8886 => 8887, + 8887 => 8886, + 8905 => 8906, + 8906 => 8905, + 8907 => 8908, + 8908 => 8907, + 8909 => 8771, + 8912 => 8913, + 8913 => 8912, + 8918 => 8919, + 8919 => 8918, + 8920 => 8921, + 8921 => 8920, + 8922 => 8923, + 8923 => 8922, + 8924 => 8925, + 8925 => 8924, + 8926 => 8927, + 8927 => 8926, + 8928 => 8929, + 8929 => 8928, + 8930 => 8931, + 8931 => 8930, + 8932 => 8933, + 8933 => 8932, + 8934 => 8935, + 8935 => 8934, + 8936 => 8937, + 8937 => 8936, + 8938 => 8939, + 8939 => 8938, + 8940 => 8941, + 8941 => 8940, + 8944 => 8945, + 8945 => 8944, + 8946 => 8954, + 8947 => 8955, + 8948 => 8956, + 8950 => 8957, + 8951 => 8958, + 8954 => 8946, + 8955 => 8947, + 8956 => 8948, + 8957 => 8950, + 8958 => 8951, + 8968 => 8969, + 8969 => 8968, + 8970 => 8971, + 8971 => 8970, + 9001 => 9002, + 9002 => 9001, + 10088 => 10089, + 10089 => 10088, + 10090 => 10091, + 10091 => 10090, + 10092 => 10093, + 10093 => 10092, + 10094 => 10095, + 10095 => 10094, + 10096 => 10097, + 10097 => 10096, + 10098 => 10099, + 10099 => 10098, + 10100 => 10101, + 10101 => 10100, + 10179 => 10180, + 10180 => 10179, + 10181 => 10182, + 10182 => 10181, + 10184 => 10185, + 10185 => 10184, + 10187 => 10189, + 10189 => 10187, + 10197 => 10198, + 10198 => 10197, + 10205 => 10206, + 10206 => 10205, + 10210 => 10211, + 10211 => 10210, + 10212 => 10213, + 10213 => 10212, + 10214 => 10215, + 10215 => 10214, + 10216 => 10217, + 10217 => 10216, + 10218 => 10219, + 10219 => 10218, + 10220 => 10221, + 10221 => 10220, + 10222 => 10223, + 10223 => 10222, + 10627 => 10628, + 10628 => 10627, + 10629 => 10630, + 10630 => 10629, + 10631 => 10632, + 10632 => 10631, + 10633 => 10634, + 10634 => 10633, + 10635 => 10636, + 10636 => 10635, + 10637 => 10640, + 10638 => 10639, + 10639 => 10638, + 10640 => 10637, + 10641 => 10642, + 10642 => 10641, + 10643 => 10644, + 10644 => 10643, + 10645 => 10646, + 10646 => 10645, + 10647 => 10648, + 10648 => 10647, + 10680 => 8856, + 10688 => 10689, + 10689 => 10688, + 10692 => 10693, + 10693 => 10692, + 10703 => 10704, + 10704 => 10703, + 10705 => 10706, + 10706 => 10705, + 10708 => 10709, + 10709 => 10708, + 10712 => 10713, + 10713 => 10712, + 10714 => 10715, + 10715 => 10714, + 10741 => 8725, + 10744 => 10745, + 10745 => 10744, + 10748 => 10749, + 10749 => 10748, + 10795 => 10796, + 10796 => 10795, + 10797 => 10798, + 10798 => 10797, + 10804 => 10805, + 10805 => 10804, + 10812 => 10813, + 10813 => 10812, + 10852 => 10853, + 10853 => 10852, + 10873 => 10874, + 10874 => 10873, + 10877 => 10878, + 10878 => 10877, + 10879 => 10880, + 10880 => 10879, + 10881 => 10882, + 10882 => 10881, + 10883 => 10884, + 10884 => 10883, + 10891 => 10892, + 10892 => 10891, + 10897 => 10898, + 10898 => 10897, + 10899 => 10900, + 10900 => 10899, + 10901 => 10902, + 10902 => 10901, + 10903 => 10904, + 10904 => 10903, + 10905 => 10906, + 10906 => 10905, + 10907 => 10908, + 10908 => 10907, + 10913 => 10914, + 10914 => 10913, + 10918 => 10919, + 10919 => 10918, + 10920 => 10921, + 10921 => 10920, + 10922 => 10923, + 10923 => 10922, + 10924 => 10925, + 10925 => 10924, + 10927 => 10928, + 10928 => 10927, + 10931 => 10932, + 10932 => 10931, + 10939 => 10940, + 10940 => 10939, + 10941 => 10942, + 10942 => 10941, + 10943 => 10944, + 10944 => 10943, + 10945 => 10946, + 10946 => 10945, + 10947 => 10948, + 10948 => 10947, + 10949 => 10950, + 10950 => 10949, + 10957 => 10958, + 10958 => 10957, + 10959 => 10960, + 10960 => 10959, + 10961 => 10962, + 10962 => 10961, + 10963 => 10964, + 10964 => 10963, + 10965 => 10966, + 10966 => 10965, + 10974 => 8870, + 10979 => 8873, + 10980 => 8872, + 10981 => 8875, + 10988 => 10989, + 10989 => 10988, + 10999 => 11000, + 11000 => 10999, + 11001 => 11002, + 11002 => 11001, + 11778 => 11779, + 11779 => 11778, + 11780 => 11781, + 11781 => 11780, + 11785 => 11786, + 11786 => 11785, + 11788 => 11789, + 11789 => 11788, + 11804 => 11805, + 11805 => 11804, + 11808 => 11809, + 11809 => 11808, + 11810 => 11811, + 11811 => 11810, + 11812 => 11813, + 11813 => 11812, + 11814 => 11815, + 11815 => 11814, + 11816 => 11817, + 11817 => 11816, + 12296 => 12297, + 12297 => 12296, + 12298 => 12299, + 12299 => 12298, + 12300 => 12301, + 12301 => 12300, + 12302 => 12303, + 12303 => 12302, + 12304 => 12305, + 12305 => 12304, + 12308 => 12309, + 12309 => 12308, + 12310 => 12311, + 12311 => 12310, + 12312 => 12313, + 12313 => 12312, + 12314 => 12315, + 12315 => 12314, + 65113 => 65114, + 65114 => 65113, + 65115 => 65116, + 65116 => 65115, + 65117 => 65118, + 65118 => 65117, + 65124 => 65125, + 65125 => 65124, + 65288 => 65289, + 65289 => 65288, + 65308 => 65310, + 65310 => 65308, + 65339 => 65341, + 65341 => 65339, + 65371 => 65373, + 65373 => 65371, + 65375 => 65376, + 65376 => 65375, + 65378 => 65379, + 65379 => 65378, + ]; + + + /* index tables for the database records */ + + private static $index0 = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 54, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 55, 56, 57, 57, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 69, 70, 70, + 71, 69, 70, 70, 72, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 70, 70, 70, 88, 89, 90, 91, 92, 70, 93, 70, 94, + 95, 70, 70, 70, 70, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 97, 97, 97, + 98, 99, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 100, 100, 100, 100, + 101, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 102, 102, + 103, 70, 70, 70, 70, 104, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 105, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 106, 107, 108, 109, 110, + 111, 112, 113, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 114, 70, 115, 116, 117, 118, 119, 120, + 121, 122, 70, 70, 70, 70, 70, 70, 70, 70, 52, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 123, 52, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 124, 125, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 76, 76, 127, 126, 126, 126, 126, 128, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 128, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 129, 130, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 73, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 131, 73, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 131, + ]; + + private static $index1 = [ + 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 0, 0, 0, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 29, 31, 32, + 33, 34, 35, 27, 30, 29, 27, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 27, 27, 49, 27, 27, 27, 27, 27, 27, 27, 50, 51, 52, 27, 53, 54, + 53, 54, 54, 54, 54, 54, 55, 54, 54, 54, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 65, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 97, 97, 97, 98, 98, 98, 98, 99, 100, 101, 101, 101, 101, 102, 103, + 101, 101, 101, 101, 101, 101, 104, 105, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 106, 107, 108, 108, 108, 109, 110, 111, 112, + 112, 112, 112, 113, 114, 115, 116, 117, 118, 119, 120, 106, 121, 121, + 121, 122, 123, 106, 124, 125, 126, 127, 128, 128, 128, 128, 129, 130, + 131, 132, 133, 134, 135, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 145, 145, + 146, 147, 148, 149, 128, 128, 128, 128, 128, 128, 150, 150, 150, 150, + 151, 152, 153, 106, 154, 155, 156, 156, 156, 157, 158, 159, 160, 160, + 161, 162, 163, 164, 165, 166, 167, 167, 167, 168, 106, 106, 106, 106, + 106, 106, 106, 106, 169, 170, 106, 106, 106, 106, 106, 106, 171, 172, + 173, 174, 175, 176, 176, 176, 176, 176, 176, 177, 178, 179, 180, 176, + 181, 182, 183, 184, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 106, 214, 215, 216, 217, 217, 218, + 219, 220, 221, 222, 223, 106, 224, 225, 226, 106, 227, 228, 229, 230, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 106, 241, 242, + 243, 244, 245, 242, 246, 247, 248, 249, 250, 106, 251, 252, 253, 254, + 255, 256, 257, 258, 258, 257, 259, 260, 261, 262, 263, 264, 265, 266, + 106, 267, 268, 269, 270, 271, 271, 270, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 106, 281, 282, 283, 284, 284, 284, 284, 285, 286, 287, + 288, 106, 289, 290, 291, 292, 293, 294, 295, 296, 294, 294, 297, 298, + 295, 299, 300, 301, 106, 106, 302, 106, 303, 304, 304, 304, 304, 304, + 305, 306, 307, 308, 309, 310, 106, 106, 106, 106, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 106, 106, 106, 106, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 331, 331, 331, 333, 334, 335, + 336, 337, 338, 339, 338, 338, 338, 340, 341, 342, 343, 344, 106, 106, + 106, 106, 345, 345, 345, 345, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 345, 356, 357, 349, 358, 359, 359, 359, 359, 360, 361, + 362, 362, 362, 362, 362, 363, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, + 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 366, 366, 366, 366, + 366, 366, 366, 366, 366, 367, 368, 367, 366, 366, 366, 366, 366, 367, + 366, 366, 366, 366, 367, 368, 367, 366, 368, 366, 366, 366, 366, 366, + 366, 366, 367, 366, 366, 366, 366, 366, 366, 366, 366, 369, 370, 371, + 372, 373, 366, 366, 374, 375, 376, 376, 376, 376, 376, 376, 376, 376, + 376, 376, 377, 106, 378, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 380, 379, 379, + 381, 382, 382, 383, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, + 386, 106, 387, 388, 389, 106, 390, 390, 391, 106, 392, 392, 393, 106, + 394, 395, 396, 106, 397, 397, 397, 397, 397, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 412, 412, 412, + 413, 412, 412, 412, 412, 412, 412, 106, 412, 412, 412, 412, 412, 414, + 379, 379, 379, 379, 379, 379, 379, 379, 415, 106, 416, 416, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 424, 424, 425, 426, 106, 427, 427, + 427, 427, 427, 428, 429, 429, 430, 431, 432, 433, 434, 434, 434, 434, + 435, 435, 436, 437, 438, 438, 438, 438, 438, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 445, 446, 447, 448, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 449, 450, 450, 450, 450, 450, 451, 452, 453, 454, + 455, 456, 457, 458, 459, 460, 461, 462, 462, 462, 463, 464, 465, 466, + 467, 467, 467, 467, 468, 469, 470, 471, 472, 472, 472, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 481, 481, 482, 106, 106, 106, 106, + 106, 106, 106, 106, 483, 106, 484, 485, 486, 487, 488, 106, 54, 54, 54, + 54, 489, 490, 56, 56, 56, 56, 56, 491, 492, 493, 54, 494, 54, 54, 54, + 495, 56, 56, 56, 496, 497, 498, 499, 500, 501, 106, 106, 502, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 503, 504, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 505, 506, 507, 508, 505, 506, + 505, 506, 507, 508, 505, 509, 505, 506, 505, 507, 505, 510, 505, 510, + 505, 510, 511, 512, 513, 514, 515, 516, 505, 517, 518, 519, 520, 521, + 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, + 536, 537, 56, 538, 539, 540, 539, 541, 106, 106, 542, 543, 544, 545, 546, + 106, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, + 560, 559, 561, 562, 563, 564, 565, 566, 567, 568, 569, 568, 570, 571, + 568, 572, 568, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, + 584, 585, 586, 587, 588, 583, 583, 589, 590, 591, 592, 593, 583, 583, + 594, 574, 595, 596, 583, 583, 597, 583, 583, 568, 598, 599, 568, 600, + 601, 602, 603, 603, 603, 603, 603, 603, 603, 603, 604, 568, 568, 605, + 606, 574, 574, 607, 568, 568, 568, 568, 573, 608, 568, 609, 106, 568, + 568, 568, 568, 610, 106, 106, 106, 568, 611, 106, 106, 612, 612, 612, + 612, 612, 613, 613, 614, 615, 615, 615, 615, 615, 615, 615, 615, 615, + 616, 612, 612, 617, 617, 617, 617, 617, 617, 617, 617, 617, 618, 617, + 617, 617, 617, 618, 568, 617, 617, 619, 568, 620, 569, 621, 622, 623, + 624, 569, 568, 619, 572, 568, 574, 625, 626, 622, 627, 568, 568, 568, + 568, 628, 568, 568, 568, 629, 630, 568, 568, 568, 568, 568, 631, 568, + 632, 568, 631, 633, 634, 617, 617, 635, 617, 617, 617, 636, 568, 568, + 568, 568, 568, 568, 637, 568, 568, 572, 568, 568, 638, 639, 612, 640, + 640, 641, 568, 568, 568, 568, 568, 642, 643, 644, 645, 646, 647, 574, + 574, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 574, 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 649, 650, 650, 651, 583, 583, 574, + 652, 597, 653, 654, 655, 656, 657, 658, 659, 574, 660, 583, 661, 662, + 663, 664, 645, 574, 574, 586, 652, 664, 665, 666, 667, 583, 583, 583, + 583, 668, 669, 583, 583, 583, 583, 670, 671, 672, 645, 673, 674, 568, + 568, 568, 568, 568, 568, 574, 574, 675, 676, 677, 678, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 679, 679, 679, 679, 679, 680, 681, 681, 681, 681, 681, + 682, 683, 684, 685, 686, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 687, 688, 689, 690, 691, 691, 691, 691, 692, 693, 694, 694, 694, 694, + 694, 694, 694, 695, 696, 697, 366, 366, 368, 106, 368, 368, 368, 368, + 368, 368, 368, 368, 698, 698, 698, 698, 699, 700, 701, 702, 703, 704, + 529, 705, 106, 106, 106, 106, 106, 106, 106, 106, 706, 706, 706, 707, + 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 708, 106, 706, 706, + 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, + 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 709, 106, 106, 106, + 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 721, 721, + 721, 721, 721, 721, 721, 721, 722, 723, 724, 725, 725, 725, 725, 725, + 725, 725, 725, 725, 725, 726, 727, 728, 728, 728, 728, 729, 730, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 731, 732, 733, 728, 728, + 728, 734, 710, 710, 710, 710, 711, 106, 725, 725, 735, 735, 735, 736, + 737, 738, 733, 733, 733, 739, 740, 741, 735, 735, 735, 742, 737, 738, + 733, 733, 733, 733, 743, 741, 733, 744, 745, 745, 745, 745, 745, 746, + 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 733, 733, 733, + 747, 748, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 749, + 733, 733, 733, 747, 750, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 752, 753, 568, 568, 568, 568, 568, 568, + 568, 568, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 754, + 753, 753, 753, 753, 753, 753, 755, 755, 756, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 755, 755, 757, 758, 758, 758, 758, 758, 758, 759, 106, 760, 760, + 760, 760, 760, 761, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, + 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, + 762, 762, 762, 762, 762, 762, 762, 762, 762, 763, 762, 762, 764, 765, + 106, 106, 101, 101, 101, 101, 101, 766, 767, 768, 101, 101, 101, 769, + 770, 770, 770, 770, 770, 770, 770, 770, 771, 772, 773, 106, 64, 64, 774, + 775, 776, 27, 777, 27, 27, 27, 27, 27, 27, 27, 778, 779, 27, 780, 781, + 106, 27, 782, 106, 106, 106, 106, 106, 106, 106, 106, 106, 783, 784, 785, + 786, 786, 787, 788, 789, 790, 791, 791, 791, 791, 791, 791, 792, 106, + 793, 794, 794, 794, 794, 794, 795, 796, 797, 798, 799, 800, 801, 801, + 802, 803, 804, 805, 806, 806, 807, 808, 809, 809, 810, 811, 812, 813, + 364, 364, 364, 814, 815, 816, 816, 816, 816, 816, 817, 818, 819, 820, + 821, 822, 106, 106, 106, 106, 823, 823, 823, 823, 823, 824, 825, 106, + 826, 827, 828, 829, 345, 345, 830, 831, 832, 832, 832, 832, 832, 832, + 833, 834, 835, 106, 106, 836, 837, 838, 839, 106, 840, 840, 840, 106, + 368, 368, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 837, 837, 837, 837, 841, 842, 843, 844, + 845, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 847, 106, 365, 365, 848, 849, 365, 365, 365, 365, 365, 850, 851, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 852, 851, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 852, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 852, + 853, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 855, 856, 856, + 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + 856, 857, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + 856, 858, 753, 753, 753, 753, 859, 106, 860, 861, 121, 862, 863, 864, + 865, 121, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 866, 867, 868, 106, 869, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 870, 106, 106, 128, 128, 128, 128, + 128, 128, 128, 128, 871, 128, 128, 128, 128, 128, 128, 106, 106, 106, + 106, 106, 128, 872, 873, 873, 874, 875, 501, 106, 876, 877, 878, 879, + 880, 881, 882, 883, 884, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 885, 886, 887, 888, 889, 890, 891, + 891, 892, 893, 894, 894, 895, 896, 897, 898, 897, 897, 897, 897, 899, + 900, 900, 900, 901, 902, 902, 902, 903, 904, 905, 106, 906, 907, 908, + 907, 907, 909, 907, 907, 910, 907, 911, 907, 911, 106, 106, 106, 106, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 912, 913, 914, 914, 914, 914, 914, 915, 603, 916, 916, 916, 916, + 916, 916, 917, 918, 919, 920, 568, 609, 106, 106, 106, 106, 106, 106, + 603, 603, 603, 603, 603, 921, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 922, 922, 922, 923, 924, 924, + 924, 924, 924, 924, 925, 106, 106, 106, 106, 106, 926, 926, 926, 927, + 928, 106, 929, 929, 930, 931, 106, 106, 106, 106, 106, 106, 932, 932, + 932, 933, 934, 934, 934, 934, 935, 934, 936, 106, 106, 106, 106, 106, + 937, 937, 937, 937, 937, 938, 938, 938, 938, 938, 939, 939, 939, 939, + 939, 939, 940, 940, 940, 941, 942, 943, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 944, 945, 946, 946, 946, 946, 947, 948, 949, 949, + 950, 951, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 952, 952, 953, 954, 955, 955, + 955, 956, 106, 106, 106, 106, 106, 106, 106, 106, 957, 957, 957, 957, + 958, 958, 958, 959, 106, 106, 106, 106, 106, 106, 106, 106, 960, 961, + 962, 963, 964, 964, 965, 966, 967, 106, 968, 969, 970, 970, 970, 971, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 972, 972, 972, 972, 972, 972, 973, 974, 975, 975, 976, 977, + 978, 978, 979, 980, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 981, 981, 981, 981, 981, 981, 981, 981, + 981, 982, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 983, 983, 983, 984, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 985, 986, 986, 986, 986, 986, 986, 987, 988, 989, 990, 991, 992, 993, + 106, 106, 994, 995, 995, 995, 995, 995, 996, 997, 998, 106, 999, 999, + 999, 1000, 1001, 1002, 1003, 1004, 1004, 1004, 1005, 1006, 1007, 1008, + 1009, 106, 106, 106, 106, 106, 106, 106, 1010, 1011, 1011, 1011, 1011, + 1011, 1012, 1013, 1014, 1015, 1016, 1017, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 1018, 1018, 1018, 1018, 1018, 1019, 1020, 106, 1021, 1022, 106, 106, 106, + 106, 106, 106, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1024, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, + 1025, 1025, 1025, 1025, 1026, 106, 1027, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1029, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 770, 770, 770, + 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, + 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, + 770, 770, 770, 770, 770, 770, 770, 770, 1030, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, + 1032, 106, 1033, 1034, 1034, 1034, 1034, 1035, 106, 1036, 1037, 1038, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 1039, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, + 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, + 603, 603, 603, 603, 1040, 106, 603, 603, 603, 603, 1041, 1042, 603, 603, + 603, 603, 603, 603, 1043, 1044, 1045, 1046, 1047, 1048, 603, 603, 603, + 1049, 603, 603, 603, 603, 603, 1040, 106, 106, 106, 106, 919, 919, 919, + 919, 919, 919, 919, 919, 1050, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 610, 106, 914, + 914, 1051, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 1052, 1052, 1052, 1053, 1054, 1054, 1055, 1052, + 1052, 1056, 1057, 1054, 1054, 1052, 1052, 1052, 1053, 1054, 1054, 1058, + 1059, 1060, 1056, 1061, 1062, 1054, 1052, 1052, 1052, 1053, 1054, 1054, + 1063, 1064, 1065, 1066, 1054, 1054, 1054, 1067, 1068, 1069, 1070, 1054, + 1054, 1055, 1052, 1052, 1056, 1054, 1054, 1054, 1052, 1052, 1052, 1053, + 1054, 1054, 1055, 1052, 1052, 1056, 1054, 1054, 1054, 1052, 1052, 1052, + 1053, 1054, 1054, 1055, 1052, 1052, 1056, 1054, 1054, 1054, 1052, 1052, + 1052, 1053, 1054, 1054, 1071, 1052, 1052, 1052, 1072, 1054, 1054, 1073, + 1074, 1052, 1052, 1075, 1054, 1054, 1076, 1055, 1052, 1052, 1077, 1054, + 1054, 1078, 1079, 1052, 1052, 1080, 1054, 1054, 1054, 1081, 1052, 1052, + 1052, 1072, 1054, 1054, 1073, 1082, 1083, 1083, 1083, 1083, 1083, 1083, + 1084, 128, 128, 128, 1085, 1086, 1087, 1088, 1089, 1090, 1085, 1091, + 1085, 1087, 1087, 1092, 128, 1093, 128, 1094, 1095, 1093, 128, 1094, 106, + 106, 106, 106, 106, 106, 1096, 106, 568, 568, 568, 568, 568, 609, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 609, 106, 568, + 610, 636, 610, 636, 568, 636, 568, 106, 106, 106, 106, 613, 1097, 615, + 615, 615, 1098, 615, 615, 615, 615, 615, 615, 615, 1099, 615, 615, 615, + 615, 615, 1100, 106, 106, 106, 106, 106, 106, 106, 106, 1101, 603, 603, + 603, 1102, 106, 733, 733, 733, 733, 733, 1103, 733, 1104, 1105, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 568, 568, 568, 568, 1106, 106, 1107, 568, 568, + 568, 568, 568, 568, 568, 568, 1108, 568, 568, 609, 106, 568, 568, 568, + 568, 1109, 611, 106, 106, 568, 568, 1106, 106, 568, 568, 568, 568, 568, + 568, 568, 610, 1110, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 1111, 568, + 568, 568, 568, 568, 568, 568, 1112, 609, 106, 568, 568, 568, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 1113, 568, 568, 568, 568, 568, 568, 568, 568, 1114, 568, 106, + 106, 106, 106, 106, 106, 568, 568, 568, 568, 568, 568, 568, 568, 1112, + 106, 106, 106, 106, 106, 106, 106, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 609, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 1115, 753, 753, 753, 753, + 753, 751, 751, 751, 751, 751, 751, 754, 753, 750, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 752, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 856, + 856, 856, 857, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 1116, 1117, 106, 106, 106, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, + 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, + 873, 873, 106, 106, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 854, 854, 1119, + ]; + + private static $index2 = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 4, 3, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, + 5, 6, 6, 7, 8, 7, 6, 6, 9, 10, 6, 11, 12, 13, 12, 12, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 12, 6, 15, 16, 15, 6, 6, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 6, 10, 18, 19, 18, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 16, + 10, 16, 1, 1, 1, 1, 1, 1, 3, 1, 1, 21, 22, 8, 8, 23, 8, 24, 22, 25, 26, + 27, 28, 16, 29, 30, 18, 31, 32, 33, 33, 25, 34, 22, 22, 25, 33, 27, 35, + 36, 36, 36, 22, 37, 37, 37, 37, 37, 37, 38, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 37, 37, 37, 37, 37, 37, 39, 38, 37, 37, 37, 37, 37, 38, 40, + 40, 40, 41, 41, 41, 41, 40, 41, 40, 40, 40, 41, 40, 40, 41, 41, 40, 41, + 40, 40, 41, 41, 41, 39, 40, 40, 40, 41, 40, 41, 40, 41, 37, 40, 37, 41, + 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 37, 40, 37, 40, 37, 41, + 37, 41, 37, 41, 37, 40, 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 38, 40, + 37, 40, 38, 40, 37, 41, 37, 41, 40, 37, 41, 37, 41, 37, 41, 38, 40, 38, + 40, 37, 40, 37, 41, 37, 40, 40, 38, 40, 37, 40, 37, 41, 37, 41, 38, 40, + 37, 41, 37, 41, 37, 37, 41, 37, 41, 37, 41, 41, 41, 37, 37, 41, 37, 41, + 37, 37, 41, 37, 37, 37, 41, 41, 37, 37, 37, 37, 41, 37, 37, 41, 37, 37, + 37, 41, 41, 41, 37, 37, 41, 37, 37, 41, 37, 41, 37, 41, 37, 37, 41, 37, + 41, 41, 37, 41, 37, 37, 41, 37, 37, 37, 41, 37, 41, 37, 37, 41, 41, 42, + 37, 41, 41, 41, 42, 42, 42, 42, 37, 43, 41, 37, 43, 41, 37, 43, 41, 37, + 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 41, 37, 41, + 41, 37, 43, 41, 37, 41, 37, 37, 37, 41, 37, 41, 41, 41, 41, 41, 41, 41, + 37, 37, 41, 37, 37, 41, 41, 37, 41, 37, 37, 37, 37, 41, 41, 40, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 41, + 41, 41, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, + 46, 46, 47, 47, 25, 47, 45, 48, 45, 48, 48, 48, 45, 48, 45, 45, 49, 46, + 47, 47, 47, 47, 47, 47, 25, 25, 25, 25, 47, 25, 47, 25, 44, 44, 44, 44, + 44, 47, 47, 47, 47, 47, 50, 50, 45, 47, 46, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53, 53, + 53, 53, 52, 54, 53, 53, 53, 53, 53, 55, 55, 53, 53, 53, 53, 55, 55, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 56, 56, 56, 56, 56, 53, 53, 53, + 53, 51, 51, 51, 51, 51, 51, 51, 51, 57, 51, 53, 53, 53, 51, 51, 51, 53, + 53, 58, 51, 51, 51, 53, 53, 53, 53, 51, 52, 53, 53, 51, 59, 60, 60, 59, + 60, 60, 59, 51, 51, 51, 51, 51, 61, 62, 61, 62, 45, 63, 61, 62, 64, 64, + 65, 62, 62, 62, 66, 64, 64, 64, 64, 64, 63, 47, 61, 66, 61, 61, 61, 64, + 61, 64, 61, 61, 62, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 64, 67, 67, 67, 67, 67, 67, 67, 61, 61, 62, 62, 62, 62, + 62, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 62, 68, 68, 68, 68, 68, 68, 68, 62, 62, 62, 62, 62, 61, 62, 62, 61, 61, + 61, 62, 62, 62, 61, 62, 61, 62, 61, 62, 61, 62, 61, 62, 69, 70, 69, 70, + 69, 70, 69, 70, 69, 70, 69, 70, 69, 70, 62, 62, 62, 62, 61, 62, 71, 61, + 62, 61, 61, 62, 62, 61, 61, 61, 72, 73, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, + 74, 74, 74, 74, 75, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 72, 75, 72, 75, 72, 75, 72, 75, 72, 75, 76, 77, 77, 78, 78, 77, + 79, 79, 72, 75, 72, 75, 72, 75, 72, 72, 75, 72, 75, 72, 75, 72, 75, 72, + 75, 72, 75, 72, 75, 75, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 64, 64, 81, 82, 82, 82, 82, 82, 82, 64, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 64, 84, 85, 64, 64, 64, 64, 86, 64, 87, + 88, 88, 88, 88, 87, 88, 88, 88, 89, 87, 88, 88, 88, 88, 88, 88, 87, 87, + 87, 87, 87, 87, 88, 88, 87, 88, 88, 89, 90, 88, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 100, 101, 102, 103, 104, 105, 106, 107, 108, 106, 88, + 87, 106, 99, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 64, + 64, 64, 64, 64, 109, 109, 109, 106, 106, 64, 64, 64, 110, 110, 110, 110, + 110, 64, 111, 111, 112, 113, 113, 114, 115, 116, 117, 117, 118, 118, 118, + 118, 118, 118, 118, 118, 119, 120, 121, 122, 64, 64, 116, 122, 123, 123, + 123, 123, 123, 123, 123, 123, 124, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 125, 126, 127, 128, 129, 130, 131, 132, 78, 78, 133, 134, + 118, 118, 118, 118, 118, 134, 118, 118, 134, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 113, 136, 136, 116, 123, 123, 137, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 116, 123, 118, 118, 118, + 118, 118, 118, 118, 138, 117, 118, 118, 118, 118, 134, 118, 139, 139, + 118, 118, 117, 134, 118, 118, 134, 123, 123, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 123, 123, 123, 141, 141, 123, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 64, 143, 144, 145, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 146, 147, 146, 146, 147, 146, 146, 147, 147, 147, 146, 147, 147, 146, + 147, 146, 146, 146, 147, 146, 147, 146, 147, 146, 147, 146, 146, 64, 64, + 144, 144, 144, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 148, 64, 64, 64, 64, 64, 64, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, 153, 152, 154, + 154, 155, 156, 156, 156, 154, 64, 64, 64, 64, 64, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, + 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 159, 158, 158, 158, + 159, 158, 158, 158, 158, 158, 64, 64, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 64, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 162, 162, 162, 64, 64, 163, 64, 123, 64, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 64, 64, 64, 64, 64, 64, 64, 118, + 118, 134, 118, 118, 134, 118, 118, 118, 134, 134, 134, 164, 165, 166, + 118, 118, 118, 134, 118, 118, 134, 134, 118, 118, 118, 118, 64, 167, 167, + 167, 168, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 167, 168, 170, 169, 168, 168, 168, 167, 167, 167, 167, 167, + 167, 167, 167, 168, 168, 168, 168, 171, 168, 168, 169, 78, 133, 172, 172, + 167, 167, 167, 169, 169, 167, 167, 84, 84, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 174, 175, 169, 169, 169, 169, 169, 169, 64, 169, 169, + 169, 169, 169, 169, 169, 64, 176, 177, 177, 64, 178, 178, 178, 178, 178, + 178, 178, 178, 64, 64, 178, 178, 64, 64, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 64, 178, 178, 178, 178, 178, 178, + 178, 64, 178, 64, 64, 64, 178, 178, 178, 178, 64, 64, 179, 178, 177, 177, + 177, 176, 176, 176, 176, 64, 64, 177, 177, 64, 64, 177, 177, 180, 178, + 64, 64, 64, 64, 64, 64, 64, 64, 177, 64, 64, 64, 64, 178, 178, 64, 178, + 178, 178, 176, 176, 64, 64, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 178, 178, 182, 182, 183, 183, 183, 183, 183, 183, 184, 182, 64, 64, + 64, 64, 64, 185, 185, 186, 64, 187, 187, 187, 187, 187, 187, 64, 64, 64, + 64, 187, 187, 64, 64, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 64, 187, 187, 187, 187, 187, 187, 187, 64, 187, 187, + 64, 187, 187, 64, 187, 187, 64, 64, 188, 64, 186, 186, 186, 185, 185, 64, + 64, 64, 64, 185, 185, 64, 64, 185, 185, 189, 64, 64, 64, 185, 64, 64, 64, + 64, 64, 64, 64, 187, 187, 187, 187, 64, 187, 64, 64, 64, 64, 64, 64, 64, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 187, 187, + 187, 185, 64, 64, 64, 191, 191, 192, 64, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 64, 193, 193, 193, 64, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 64, 193, 193, 193, 193, 193, 193, 193, + 64, 193, 193, 64, 193, 193, 193, 193, 193, 64, 64, 194, 193, 192, 192, + 192, 191, 191, 191, 191, 191, 64, 191, 191, 192, 64, 192, 192, 195, 64, + 64, 193, 64, 64, 64, 64, 64, 64, 64, 193, 193, 191, 191, 64, 64, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 197, 198, 64, 64, 64, 64, + 64, 64, 64, 199, 200, 200, 64, 201, 201, 201, 201, 201, 201, 201, 201, + 64, 64, 201, 201, 64, 64, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 64, 201, 201, 201, 201, 201, 201, 201, 64, 201, + 201, 64, 201, 201, 201, 201, 201, 64, 64, 202, 201, 200, 199, 200, 199, + 199, 199, 199, 64, 64, 200, 200, 64, 64, 200, 200, 203, 64, 64, 64, 64, + 64, 64, 64, 64, 199, 200, 64, 64, 64, 64, 201, 201, 64, 201, 201, 201, + 199, 199, 64, 64, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, + 201, 206, 206, 206, 206, 206, 206, 64, 64, 207, 208, 64, 208, 208, 208, + 208, 208, 208, 64, 64, 64, 208, 208, 208, 64, 208, 208, 208, 208, 64, 64, + 64, 208, 208, 64, 208, 64, 208, 208, 64, 64, 64, 208, 208, 64, 64, 64, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 64, 64, 64, 64, 209, + 209, 207, 209, 209, 64, 64, 64, 209, 209, 209, 64, 209, 209, 209, 210, + 64, 64, 208, 64, 64, 64, 64, 64, 64, 209, 64, 64, 64, 64, 64, 64, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, 213, 213, + 213, 213, 213, 213, 214, 213, 64, 64, 64, 64, 64, 64, 215, 215, 215, 64, + 216, 216, 216, 216, 216, 216, 216, 216, 64, 216, 216, 216, 64, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 64, 216, 216, 216, 216, 216, 64, 64, 64, 216, 217, 217, 217, + 215, 215, 215, 215, 64, 217, 217, 217, 64, 217, 217, 217, 218, 64, 64, + 64, 64, 64, 64, 64, 219, 220, 64, 216, 216, 64, 64, 64, 64, 64, 64, 216, + 216, 217, 217, 64, 64, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 222, 222, 222, 222, 222, 222, 222, 223, 64, 64, 224, 224, 64, 225, 225, + 225, 225, 225, 225, 225, 225, 64, 225, 225, 225, 64, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 64, + 225, 225, 225, 225, 225, 64, 64, 226, 225, 224, 227, 224, 224, 224, 224, + 224, 64, 227, 224, 224, 64, 224, 224, 228, 229, 64, 64, 64, 64, 64, 64, + 64, 224, 224, 64, 64, 64, 64, 64, 64, 64, 225, 64, 225, 225, 228, 228, + 64, 64, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 64, 225, 225, + 64, 64, 64, 64, 64, 64, 64, 231, 231, 64, 232, 232, 232, 232, 232, 232, + 232, 232, 64, 232, 232, 232, 64, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 64, 64, 232, 231, 231, 231, + 233, 233, 233, 233, 64, 231, 231, 231, 64, 231, 231, 231, 234, 232, 64, + 64, 64, 64, 64, 64, 64, 64, 231, 232, 232, 233, 233, 64, 64, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 236, 64, + 64, 64, 237, 232, 232, 232, 232, 232, 232, 64, 64, 238, 238, 64, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 64, 64, 64, 239, 239, 239, 239, 239, 239, 239, 239, 64, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 64, 239, 64, 64, 64, 64, + 240, 64, 64, 64, 64, 238, 238, 238, 241, 241, 241, 64, 241, 64, 238, 238, + 238, 238, 238, 238, 238, 238, 64, 64, 238, 238, 242, 64, 64, 64, 64, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 244, 243, 243, 244, 244, 244, 244, 245, 245, 246, 64, 64, 64, 64, + 247, 243, 243, 243, 243, 243, 243, 248, 244, 249, 249, 249, 249, 244, + 244, 244, 250, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, + 250, 64, 64, 64, 64, 64, 252, 252, 64, 252, 64, 64, 252, 252, 64, 252, + 64, 64, 252, 64, 64, 64, 64, 64, 64, 252, 252, 252, 252, 64, 252, 252, + 252, 252, 252, 252, 252, 64, 252, 252, 252, 64, 252, 64, 252, 64, 64, + 252, 252, 64, 252, 252, 252, 252, 253, 252, 252, 253, 253, 253, 253, 254, + 254, 64, 253, 253, 252, 64, 64, 252, 252, 252, 252, 252, 64, 255, 64, + 256, 256, 256, 256, 253, 253, 64, 64, 257, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 64, 64, 252, 252, 252, 252, 258, 259, 259, 259, 260, 260, + 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 259, + 260, 259, 259, 259, 261, 261, 259, 259, 259, 259, 259, 259, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 263, 263, 263, 263, 263, 263, + 263, 263, 263, 263, 259, 261, 259, 261, 259, 264, 265, 266, 265, 266, + 267, 267, 258, 258, 258, 258, 258, 258, 258, 258, 64, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 64, 64, 64, 64, 268, 269, 270, + 271, 270, 270, 270, 270, 270, 269, 269, 269, 269, 270, 267, 269, 270, + 272, 272, 273, 260, 272, 272, 258, 258, 258, 258, 258, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 64, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 64, 259, 259, 259, 259, 259, 259, 259, 259, + 261, 259, 259, 259, 259, 259, 259, 64, 259, 259, 260, 260, 260, 260, 260, + 274, 274, 274, 274, 260, 260, 64, 64, 64, 64, 64, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 275, 276, 276, 277, 277, 277, 277, 276, + 277, 277, 277, 277, 277, 278, 276, 279, 279, 276, 276, 277, 277, 275, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, + 281, 281, 275, 275, 275, 275, 275, 275, 276, 276, 277, 277, 275, 275, + 275, 275, 277, 277, 277, 275, 276, 276, 276, 275, 275, 276, 276, 276, + 276, 276, 276, 276, 275, 275, 275, 277, 277, 277, 277, 275, 275, 275, + 275, 275, 277, 276, 276, 277, 277, 276, 276, 276, 276, 276, 276, 282, + 275, 276, 280, 280, 276, 276, 276, 277, 283, 283, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 64, 284, 64, 64, 64, + 64, 64, 284, 64, 64, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, + 285, 84, 286, 285, 285, 285, 287, 287, 287, 287, 287, 287, 287, 287, 288, + 288, 288, 288, 288, 288, 288, 288, 289, 289, 289, 289, 289, 289, 289, + 289, 289, 64, 289, 289, 289, 289, 64, 64, 289, 289, 289, 289, 289, 289, + 289, 64, 289, 289, 289, 64, 64, 290, 290, 290, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, 64, 64, 64, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 293, 64, 64, 64, 64, 64, 64, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 64, 64, 64, 295, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 297, 297, 296, 298, 299, 299, 299, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, + 300, 301, 64, 64, 64, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, + 302, 84, 84, 84, 303, 303, 303, 64, 64, 64, 64, 64, 64, 64, 304, 304, + 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 64, 304, 304, 304, + 304, 305, 305, 306, 64, 64, 64, 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 308, 308, 309, 84, 84, 64, 310, 310, 310, 310, 310, 310, 310, + 310, 310, 310, 311, 311, 64, 64, 64, 64, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 64, 312, 312, 312, 64, 313, 313, 64, + 64, 64, 64, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 315, 315, 316, 315, 315, 315, 315, 315, 315, 315, 316, 316, 316, 316, + 316, 316, 316, 316, 315, 316, 316, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 317, 315, 318, 318, 318, 319, 318, 318, 318, 320, 314, 321, 64, + 64, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 64, 64, 64, 64, 64, + 64, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 64, 64, 64, 64, 64, + 64, 324, 324, 66, 66, 324, 66, 325, 324, 324, 324, 324, 326, 326, 326, + 327, 64, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 64, 64, 64, + 64, 64, 64, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 330, + 329, 329, 329, 329, 329, 331, 329, 64, 64, 64, 64, 64, 296, 296, 296, + 296, 296, 296, 64, 64, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 64, 64, 64, 333, 333, 333, 334, 334, 334, 334, 333, 333, + 334, 334, 334, 64, 64, 64, 64, 334, 334, 333, 334, 334, 334, 334, 334, + 334, 335, 336, 337, 64, 64, 64, 64, 338, 64, 64, 64, 339, 339, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 64, 64, 341, 341, 341, 341, 341, + 64, 64, 64, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 64, 64, 64, 64, 343, 343, 343, 343, 343, 343, 343, 343, 343, 342, 342, + 342, 342, 342, 342, 342, 343, 343, 64, 64, 64, 64, 64, 64, 344, 344, 344, + 344, 344, 344, 344, 344, 344, 344, 345, 64, 64, 64, 346, 346, 347, 347, + 347, 347, 347, 347, 347, 347, 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 349, 350, 351, 351, 351, 64, 64, 352, + 352, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 354, 355, 354, 355, 355, 355, 355, 355, 355, 355, 64, 356, 354, 355, 354, + 354, 355, 355, 355, 355, 355, 355, 355, 355, 354, 354, 354, 354, 354, + 354, 355, 355, 357, 357, 357, 357, 357, 357, 357, 357, 64, 64, 358, 359, + 359, 359, 359, 359, 359, 359, 359, 359, 359, 64, 64, 64, 64, 64, 64, 360, + 360, 360, 360, 360, 360, 360, 361, 360, 360, 360, 360, 360, 360, 64, 64, + 362, 362, 362, 362, 363, 364, 364, 364, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 365, 363, 362, 362, 362, 362, 362, 363, + 362, 363, 363, 363, 363, 363, 362, 363, 366, 364, 364, 364, 364, 364, + 364, 364, 64, 64, 64, 64, 367, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 368, 368, 368, 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, + 369, 369, 369, 369, 370, 371, 370, 370, 370, 370, 370, 370, 370, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 64, 64, 64, 372, 372, 373, 374, + 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 373, + 372, 372, 372, 372, 373, 373, 372, 372, 375, 376, 373, 373, 374, 374, + 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 374, 374, 374, 374, + 374, 374, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, + 378, 378, 379, 380, 381, 381, 380, 380, 380, 381, 380, 381, 381, 381, + 382, 382, 64, 64, 64, 64, 64, 64, 64, 64, 383, 383, 383, 383, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 385, 385, 385, + 385, 385, 385, 385, 386, 386, 386, 386, 386, 386, 386, 386, 385, 385, + 386, 387, 64, 64, 64, 388, 388, 388, 388, 388, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 64, 64, 64, 384, 384, 384, 390, 390, 390, 390, + 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391, + 391, 391, 391, 391, 391, 391, 392, 392, 392, 392, 392, 392, 393, 393, + 394, 394, 394, 394, 394, 394, 394, 394, 78, 78, 78, 84, 395, 133, 133, + 133, 133, 133, 78, 78, 133, 133, 133, 133, 78, 396, 395, 395, 395, 395, + 395, 395, 395, 397, 397, 397, 397, 133, 397, 397, 397, 397, 396, 396, 78, + 397, 397, 64, 41, 41, 41, 41, 41, 41, 62, 62, 62, 62, 62, 75, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 44, 44, 44, 44, 65, 65, 65, + 65, 65, 41, 41, 41, 41, 41, 398, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 65, 78, 78, 133, 78, 78, + 78, 78, 78, 78, 78, 133, 78, 78, 399, 400, 133, 401, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 64, + 64, 64, 64, 64, 402, 133, 78, 133, 37, 41, 37, 41, 37, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 37, 41, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, + 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 64, 64, 61, 61, 61, 61, 61, + 61, 64, 64, 64, 61, 64, 61, 64, 61, 64, 61, 403, 403, 403, 403, 403, 403, + 403, 403, 62, 62, 62, 62, 62, 64, 62, 62, 61, 61, 61, 61, 403, 63, 62, + 63, 63, 63, 62, 62, 62, 64, 62, 62, 61, 61, 61, 61, 403, 63, 63, 63, 62, + 62, 62, 62, 64, 64, 62, 62, 61, 61, 61, 61, 64, 63, 63, 63, 61, 61, 61, + 61, 61, 63, 63, 63, 64, 64, 62, 62, 62, 64, 62, 62, 61, 61, 61, 61, 403, + 63, 63, 64, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, 405, + 406, 406, 407, 408, 409, 410, 410, 409, 409, 409, 22, 66, 411, 412, 413, + 414, 411, 412, 413, 414, 22, 22, 22, 66, 22, 22, 22, 22, 415, 416, 417, + 418, 419, 420, 421, 21, 422, 423, 422, 422, 423, 22, 66, 66, 66, 28, 35, + 22, 66, 66, 22, 424, 424, 66, 66, 66, 425, 426, 427, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 428, 66, 424, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 404, 405, 405, 405, 405, 405, 64, 64, 64, 64, 64, 405, 405, 405, 405, + 405, 405, 429, 44, 64, 64, 33, 429, 429, 429, 429, 429, 430, 430, 428, + 426, 427, 431, 429, 33, 33, 33, 33, 429, 429, 429, 429, 429, 430, 430, + 428, 426, 427, 64, 44, 44, 44, 44, 44, 64, 64, 64, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 432, 247, 247, 23, 247, 247, 247, 247, 247, 247, + 64, 64, 64, 64, 64, 78, 78, 395, 395, 78, 78, 78, 78, 395, 395, 395, 78, + 78, 433, 433, 433, 433, 78, 433, 433, 433, 395, 395, 78, 133, 78, 395, + 395, 133, 133, 133, 133, 78, 64, 64, 64, 64, 64, 64, 64, 26, 26, 434, 30, + 26, 30, 26, 434, 26, 30, 34, 434, 434, 434, 34, 34, 434, 434, 434, 435, + 26, 434, 30, 26, 428, 434, 434, 434, 434, 434, 26, 26, 26, 30, 30, 26, + 434, 26, 67, 26, 434, 26, 37, 38, 434, 434, 436, 34, 434, 434, 37, 434, + 34, 397, 397, 397, 397, 34, 26, 26, 34, 34, 434, 434, 437, 428, 428, 428, + 428, 434, 34, 34, 34, 34, 26, 428, 26, 26, 41, 274, 438, 438, 438, 36, + 36, 438, 438, 438, 438, 438, 438, 36, 36, 36, 36, 438, 439, 439, 439, + 439, 439, 439, 439, 439, 439, 439, 439, 439, 440, 440, 440, 440, 439, + 439, 440, 440, 440, 440, 440, 440, 440, 440, 440, 37, 41, 440, 440, 440, + 440, 36, 64, 64, 64, 64, 64, 64, 39, 39, 39, 39, 39, 30, 30, 30, 30, 30, + 428, 428, 26, 26, 26, 26, 428, 26, 26, 428, 26, 26, 428, 26, 26, 26, 26, + 26, 26, 26, 428, 26, 26, 26, 26, 26, 26, 26, 26, 26, 30, 30, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 428, 428, 26, 26, 39, 26, 39, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 30, 26, 26, 26, 26, 428, 428, 428, 428, + 428, 428, 428, 428, 428, 428, 428, 428, 39, 437, 441, 441, 437, 428, 428, + 39, 441, 437, 437, 441, 437, 437, 428, 39, 428, 441, 430, 442, 428, 441, + 437, 428, 428, 428, 441, 437, 437, 441, 39, 441, 441, 437, 437, 39, 437, + 39, 437, 39, 39, 39, 39, 441, 441, 437, 441, 437, 437, 437, 437, 437, 39, + 39, 39, 39, 428, 437, 428, 437, 441, 441, 437, 437, 437, 437, 437, 437, + 437, 437, 437, 437, 441, 437, 437, 437, 441, 428, 428, 428, 428, 428, + 441, 437, 437, 437, 428, 428, 428, 428, 428, 428, 428, 428, 428, 437, + 441, 39, 437, 428, 441, 441, 441, 441, 437, 437, 441, 441, 428, 428, 441, + 441, 437, 437, 441, 441, 437, 437, 441, 441, 437, 437, 437, 437, 437, + 428, 428, 437, 437, 437, 437, 428, 428, 39, 428, 428, 437, 39, 428, 428, + 428, 428, 428, 428, 428, 428, 437, 437, 428, 39, 437, 437, 437, 428, 428, + 428, 428, 428, 437, 441, 428, 437, 437, 437, 437, 437, 428, 428, 437, + 437, 428, 428, 428, 428, 437, 437, 437, 437, 437, 437, 437, 437, 428, + 428, 437, 437, 437, 437, 26, 26, 26, 26, 26, 26, 30, 26, 26, 26, 26, 26, + 437, 437, 26, 26, 26, 26, 26, 26, 26, 443, 444, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 26, 428, 26, 26, 26, 26, 26, 26, 26, 26, 274, 26, 26, 26, + 26, 26, 428, 428, 428, 428, 428, 428, 428, 428, 428, 26, 26, 26, 26, 428, + 428, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 64, 64, 64, 64, 26, 26, 26, + 26, 26, 26, 26, 64, 26, 26, 26, 64, 64, 64, 64, 64, 36, 36, 36, 36, 36, + 36, 36, 36, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 445, 445, + 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, 438, 36, 36, + 36, 36, 36, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 26, 26, 26, + 26, 26, 26, 30, 30, 30, 30, 26, 26, 30, 30, 26, 30, 30, 30, 30, 30, 26, + 26, 30, 30, 26, 26, 30, 39, 26, 26, 26, 26, 30, 30, 26, 26, 30, 39, 26, + 26, 26, 26, 30, 30, 30, 26, 26, 30, 26, 26, 30, 30, 26, 26, 26, 26, 26, + 30, 30, 26, 26, 30, 26, 26, 26, 26, 30, 30, 26, 26, 26, 26, 30, 26, 30, + 26, 30, 26, 30, 26, 26, 26, 26, 26, 30, 30, 26, 30, 30, 30, 26, 30, 30, + 30, 30, 26, 30, 30, 26, 39, 26, 26, 26, 26, 26, 26, 30, 30, 26, 26, 26, + 26, 274, 26, 26, 26, 26, 26, 26, 26, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 26, 30, 30, 30, 26, 30, 26, 26, 26, 26, 64, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 30, 26, 26, 426, 427, 426, 427, 426, 427, 426, + 427, 426, 427, 426, 427, 426, 427, 36, 36, 438, 438, 438, 438, 438, 438, + 438, 438, 438, 438, 438, 438, 26, 26, 26, 26, 437, 428, 428, 437, 437, + 426, 427, 428, 437, 437, 428, 437, 437, 437, 428, 428, 428, 428, 428, + 437, 437, 437, 437, 428, 428, 428, 428, 428, 437, 437, 437, 428, 428, + 428, 437, 437, 437, 437, 9, 10, 9, 10, 9, 10, 9, 10, 426, 427, 446, 446, + 446, 446, 446, 446, 446, 446, 428, 428, 428, 426, 427, 9, 10, 426, 427, + 426, 427, 426, 427, 426, 427, 426, 427, 428, 428, 437, 437, 437, 437, + 437, 437, 428, 428, 428, 428, 428, 428, 428, 428, 437, 428, 428, 428, + 428, 437, 437, 437, 437, 437, 428, 437, 437, 428, 428, 426, 427, 426, + 427, 437, 428, 428, 428, 428, 437, 428, 437, 437, 437, 428, 428, 437, + 437, 428, 428, 428, 428, 428, 428, 428, 428, 428, 428, 437, 437, 437, + 437, 437, 437, 428, 428, 426, 427, 428, 428, 428, 428, 437, 437, 437, + 437, 437, 437, 437, 437, 437, 437, 437, 428, 437, 437, 437, 437, 428, + 428, 437, 428, 437, 428, 428, 437, 428, 437, 437, 437, 437, 428, 428, + 428, 428, 428, 437, 437, 428, 428, 428, 428, 437, 437, 437, 437, 428, + 437, 437, 428, 428, 437, 437, 428, 428, 428, 428, 437, 437, 437, 437, + 437, 437, 437, 437, 437, 437, 437, 428, 428, 437, 437, 437, 437, 437, + 437, 437, 437, 428, 437, 437, 437, 437, 437, 437, 437, 437, 428, 428, + 428, 428, 428, 437, 428, 437, 428, 428, 428, 437, 437, 437, 437, 437, + 428, 428, 428, 428, 437, 428, 428, 428, 437, 437, 437, 437, 437, 428, + 437, 428, 428, 428, 428, 428, 428, 428, 26, 26, 428, 428, 428, 428, 428, + 428, 64, 64, 64, 26, 26, 26, 26, 26, 30, 30, 30, 30, 30, 64, 64, 64, 64, + 64, 64, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 447, 447, 64, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, + 448, 448, 448, 64, 37, 41, 37, 37, 37, 41, 41, 37, 41, 37, 41, 37, 41, + 37, 37, 37, 37, 41, 37, 41, 41, 37, 41, 41, 41, 41, 41, 41, 44, 44, 37, + 37, 69, 70, 69, 70, 70, 449, 449, 449, 449, 449, 449, 69, 70, 69, 70, + 450, 450, 450, 69, 70, 64, 64, 64, 64, 64, 451, 451, 451, 451, 452, 451, + 451, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, + 453, 64, 453, 64, 64, 64, 64, 64, 453, 64, 64, 454, 454, 454, 454, 454, + 454, 454, 454, 64, 64, 64, 64, 64, 64, 64, 455, 456, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 457, 77, 77, 77, 77, 77, 77, 77, 77, + 66, 66, 28, 35, 28, 35, 66, 66, 66, 28, 35, 66, 28, 35, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 410, 66, 66, 410, 66, 28, 35, 66, 66, 28, 35, 426, + 427, 426, 427, 426, 427, 426, 427, 66, 66, 66, 66, 66, 45, 66, 66, 410, + 410, 64, 64, 64, 64, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 64, 458, 458, 458, 458, 458, 458, 458, 458, 458, 64, 64, 64, 64, 458, + 458, 458, 458, 458, 458, 64, 64, 459, 459, 459, 459, 459, 459, 459, 459, + 459, 459, 459, 459, 64, 64, 64, 64, 460, 461, 461, 461, 459, 462, 463, + 464, 443, 444, 443, 444, 443, 444, 443, 444, 443, 444, 459, 459, 443, + 444, 443, 444, 443, 444, 443, 444, 465, 466, 467, 467, 459, 464, 464, + 464, 464, 464, 464, 464, 464, 464, 468, 469, 470, 471, 472, 472, 465, + 473, 473, 473, 473, 473, 459, 459, 464, 464, 464, 462, 463, 461, 459, 26, + 64, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, + 474, 474, 474, 474, 474, 474, 474, 474, 64, 64, 475, 475, 476, 476, 477, + 477, 474, 465, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, + 478, 478, 478, 478, 478, 478, 478, 461, 473, 479, 479, 478, 64, 64, 64, + 64, 64, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 64, 64, 64, 287, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 287, 287, 64, 481, 481, 482, 482, 482, 482, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 480, 480, 480, 64, 64, 64, 64, + 64, 483, 483, 483, 483, 483, 483, 483, 483, 483, 483, 483, 483, 483, 484, + 484, 64, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 481, 481, 481, + 481, 481, 481, 485, 485, 485, 485, 485, 485, 485, 485, 459, 486, 486, + 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 483, + 483, 483, 483, 484, 484, 484, 481, 481, 486, 486, 486, 486, 486, 486, + 486, 481, 481, 481, 481, 459, 459, 459, 459, 487, 487, 487, 487, 487, + 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 64, 481, 481, 481, 481, + 481, 481, 481, 459, 459, 459, 459, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 459, 459, 488, 489, 489, 489, 489, 489, 489, 489, + 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 488, + 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 489, 489, 489, 489, + 488, 490, 490, 490, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 492, 491, 491, 491, 491, 491, 491, 491, 64, 64, 64, 493, + 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 64, + 494, 494, 494, 494, 494, 494, 494, 494, 495, 495, 495, 495, 495, 495, + 496, 496, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, + 498, 499, 499, 499, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, + 497, 497, 64, 64, 64, 64, 72, 75, 72, 75, 72, 75, 501, 77, 79, 79, 79, + 502, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 502, 503, 64, 64, 64, 64, + 64, 64, 64, 77, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + 504, 504, 504, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 506, + 506, 507, 507, 507, 507, 507, 507, 47, 47, 47, 47, 47, 47, 47, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 47, 47, 37, 41, 37, 41, 37, 41, 41, 41, 37, + 41, 37, 41, 37, 41, 44, 41, 41, 41, 41, 41, 41, 41, 41, 37, 41, 37, 41, + 37, 37, 41, 45, 508, 508, 37, 41, 37, 41, 64, 37, 41, 37, 41, 64, 64, 64, + 64, 37, 41, 37, 64, 64, 64, 64, 64, 44, 44, 41, 42, 42, 42, 42, 42, 509, + 509, 510, 509, 509, 509, 511, 509, 509, 509, 509, 510, 509, 509, 509, + 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 512, 512, + 510, 510, 512, 513, 513, 513, 513, 64, 64, 64, 64, 514, 514, 514, 514, + 514, 514, 274, 274, 247, 436, 64, 64, 64, 64, 64, 64, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 516, 516, 516, 516, 517, 517, + 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, + 518, 518, 518, 518, 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, + 517, 517, 517, 517, 517, 517, 519, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 520, 520, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 64, 64, 64, + 64, 64, 64, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 169, 169, + 169, 169, 169, 169, 174, 174, 174, 169, 64, 64, 64, 64, 522, 522, 522, + 522, 522, 522, 522, 522, 522, 522, 523, 523, 523, 523, 523, 523, 523, + 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 524, + 524, 524, 524, 524, 525, 525, 525, 526, 526, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 528, 528, 528, 528, + 528, 528, 528, 528, 528, 528, 528, 529, 530, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 531, 287, 287, 287, 287, 287, 64, 64, 64, 532, 532, 532, + 533, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, + 534, 534, 535, 533, 533, 532, 532, 532, 532, 533, 533, 532, 533, 533, + 533, 536, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, + 537, 64, 538, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 64, 64, + 64, 64, 537, 537, 540, 540, 540, 540, 540, 540, 540, 540, 540, 541, 541, + 541, 541, 541, 541, 542, 542, 541, 541, 542, 542, 541, 541, 64, 540, 540, + 540, 541, 540, 540, 540, 540, 540, 540, 540, 540, 541, 542, 64, 64, 543, + 543, 543, 543, 543, 543, 543, 543, 543, 543, 64, 64, 544, 544, 544, 544, + 545, 275, 275, 275, 275, 275, 275, 283, 283, 283, 275, 276, 64, 64, 64, + 64, 546, 546, 546, 546, 546, 546, 546, 546, 547, 546, 547, 547, 548, 546, + 546, 547, 547, 546, 546, 546, 546, 546, 547, 547, 546, 547, 546, 64, 64, + 64, 64, 64, 64, 64, 64, 546, 546, 549, 550, 550, 551, 551, 551, 551, 551, + 551, 551, 551, 551, 551, 551, 552, 553, 553, 552, 552, 554, 554, 551, + 555, 555, 552, 556, 64, 64, 289, 289, 289, 289, 289, 289, 64, 551, 551, + 551, 552, 552, 553, 552, 552, 553, 552, 552, 554, 552, 556, 64, 64, 557, + 557, 557, 557, 557, 557, 557, 557, 557, 557, 64, 64, 64, 64, 64, 64, 287, + 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, + 558, 558, 558, 558, 287, 64, 64, 64, 64, 288, 288, 288, 288, 288, 288, + 288, 64, 64, 64, 64, 288, 288, 288, 288, 288, 288, 288, 288, 288, 64, 64, + 64, 64, 559, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 559, + 560, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 560, 488, 488, 488, 488, + 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 490, 490, 488, 488, + 490, 490, 490, 490, 490, 490, 41, 41, 41, 41, 41, 41, 41, 64, 64, 64, 64, + 83, 83, 83, 83, 83, 64, 64, 64, 64, 64, 109, 562, 109, 109, 563, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 64, 109, 109, + 109, 109, 109, 64, 109, 64, 109, 109, 64, 109, 109, 64, 109, 109, 123, + 123, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, + 564, 564, 564, 64, 64, 64, 64, 64, 64, 64, 64, 64, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 413, 565, 64, 64, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 114, 26, 64, 64, 58, 58, 58, 58, 58, 58, + 58, 58, 461, 461, 461, 461, 461, 461, 461, 466, 467, 461, 64, 64, 64, 64, + 64, 64, 461, 465, 465, 566, 566, 466, 467, 466, 467, 466, 467, 466, 467, + 466, 467, 466, 467, 466, 467, 466, 467, 461, 461, 466, 467, 461, 461, + 461, 461, 566, 566, 566, 567, 461, 567, 64, 461, 567, 461, 461, 465, 443, + 444, 443, 444, 443, 444, 568, 461, 461, 569, 570, 571, 571, 572, 64, 461, + 573, 568, 461, 64, 64, 64, 64, 123, 123, 123, 123, 123, 64, 123, 123, + 123, 123, 123, 123, 123, 64, 64, 405, 64, 574, 574, 575, 576, 575, 574, + 574, 577, 578, 574, 579, 580, 581, 580, 580, 582, 582, 582, 582, 582, + 582, 582, 582, 582, 582, 580, 574, 583, 584, 583, 574, 574, 585, 585, + 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 577, 574, 578, 586, 587, 586, 588, 588, 588, 588, 588, 588, + 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 577, 584, + 578, 584, 577, 578, 589, 590, 591, 589, 589, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 593, 592, 592, 592, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 593, 593, 594, 594, 594, 594, 594, 594, 594, + 594, 594, 594, 594, 594, 594, 594, 594, 64, 64, 64, 594, 594, 594, 594, + 594, 594, 64, 64, 594, 594, 594, 64, 64, 64, 576, 576, 584, 586, 595, + 576, 576, 64, 596, 597, 597, 597, 597, 596, 596, 64, 64, 598, 598, 598, + 26, 30, 64, 64, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 64, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 64, 599, 599, + 599, 64, 599, 599, 64, 599, 599, 599, 599, 599, 599, 599, 64, 64, 599, + 599, 599, 64, 64, 64, 64, 64, 84, 66, 84, 64, 64, 64, 64, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 64, 64, 64, 274, 600, + 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 601, 601, + 601, 601, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, + 602, 602, 602, 602, 602, 601, 64, 64, 64, 64, 64, 274, 274, 274, 274, + 274, 133, 64, 64, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, + 603, 603, 64, 64, 64, 604, 604, 604, 604, 604, 604, 604, 604, 604, 64, + 64, 64, 64, 64, 64, 64, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 64, 606, 606, 606, 606, 64, 64, 64, 64, 607, + 607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 607, 607, 607, 607, + 607, 607, 607, 608, 64, 64, 64, 64, 64, 609, 609, 609, 609, 609, 609, + 609, 609, 609, 609, 609, 609, 609, 609, 64, 610, 611, 611, 611, 611, 611, + 611, 611, 611, 611, 611, 611, 611, 64, 64, 64, 64, 612, 613, 613, 613, + 613, 613, 64, 64, 614, 614, 614, 614, 614, 614, 614, 614, 615, 615, 615, + 615, 615, 615, 615, 615, 616, 616, 616, 616, 616, 616, 616, 616, 617, + 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 64, 64, + 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 64, 64, 64, 64, 64, 64, + 619, 619, 619, 619, 619, 619, 64, 64, 619, 64, 619, 619, 619, 619, 619, + 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, 619, + 619, 64, 619, 619, 64, 64, 64, 619, 64, 64, 619, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 64, 621, 622, 622, 622, 622, + 622, 622, 622, 622, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, + 623, 623, 623, 623, 624, 624, 624, 624, 624, 624, 64, 64, 64, 625, 626, + 626, 626, 626, 626, 626, 626, 626, 626, 626, 64, 64, 64, 64, 64, 627, + 628, 628, 628, 628, 628, 628, 628, 628, 629, 629, 629, 629, 629, 629, + 629, 629, 64, 64, 64, 64, 64, 64, 629, 629, 630, 631, 631, 631, 64, 631, + 631, 64, 64, 64, 64, 64, 631, 632, 631, 633, 630, 630, 630, 630, 64, 630, + 630, 630, 64, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, + 630, 630, 630, 630, 630, 630, 630, 64, 64, 64, 64, 633, 634, 632, 64, 64, + 64, 64, 635, 636, 636, 636, 636, 636, 636, 636, 636, 637, 637, 637, 637, + 637, 637, 637, 637, 637, 64, 64, 64, 64, 64, 64, 64, 638, 638, 638, 638, + 638, 638, 638, 638, 638, 638, 638, 638, 638, 639, 639, 640, 641, 641, + 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 64, 64, 64, + 642, 642, 642, 642, 642, 642, 642, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 64, 64, 644, 644, 644, 644, 644, 644, + 644, 644, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 64, 64, + 64, 64, 64, 646, 646, 646, 646, 646, 646, 646, 646, 647, 647, 647, 647, + 647, 647, 647, 647, 647, 64, 64, 64, 64, 64, 64, 64, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 64, 649, 650, 649, + 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 650, + 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 652, + 653, 653, 653, 653, 653, 653, 653, 64, 64, 64, 64, 654, 654, 654, 654, + 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, + 654, 654, 655, 655, 655, 655, 655, 655, 655, 655, 655, 655, 656, 656, + 657, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, + 657, 657, 657, 656, 656, 656, 656, 657, 657, 659, 660, 661, 661, 662, + 661, 661, 661, 661, 64, 64, 64, 64, 64, 64, 663, 663, 663, 663, 663, 663, + 663, 663, 663, 64, 64, 64, 64, 64, 64, 64, 664, 664, 664, 664, 664, 664, + 664, 664, 664, 664, 64, 64, 64, 64, 64, 64, 665, 665, 665, 666, 666, 666, + 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, + 666, 666, 666, 667, 667, 667, 667, 667, 668, 667, 667, 667, 667, 667, + 667, 669, 669, 64, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 671, + 671, 671, 671, 64, 64, 64, 64, 672, 672, 673, 674, 674, 674, 674, 674, + 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 673, 673, 673, + 672, 672, 672, 672, 672, 672, 672, 672, 672, 673, 675, 674, 674, 674, + 674, 676, 676, 676, 676, 64, 64, 64, 64, 64, 64, 64, 677, 677, 677, 677, + 677, 677, 677, 677, 677, 677, 64, 64, 64, 64, 64, 64, 678, 678, 678, 678, + 678, 678, 678, 678, 678, 678, 678, 679, 680, 679, 680, 680, 679, 679, + 679, 679, 679, 679, 681, 682, 683, 683, 683, 683, 683, 683, 683, 683, + 683, 683, 64, 64, 64, 64, 64, 64, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 64, 685, 685, 685, 685, 685, 685, 685, + 685, 685, 685, 685, 64, 64, 64, 64, 64, 686, 686, 686, 686, 64, 64, 64, + 64, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, + 687, 64, 504, 64, 64, 64, 64, 64, 64, 64, 688, 688, 688, 688, 688, 688, + 688, 688, 688, 688, 688, 688, 688, 64, 64, 64, 688, 689, 689, 689, 689, + 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, + 689, 689, 689, 689, 64, 64, 64, 64, 64, 64, 64, 64, 690, 690, 690, 690, + 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 478, + 474, 64, 64, 64, 64, 64, 64, 274, 274, 274, 274, 274, 274, 64, 64, 274, + 274, 274, 274, 274, 274, 274, 64, 64, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 692, 692, 395, 395, 395, 274, 274, 274, 693, + 692, 692, 692, 692, 692, 405, 405, 405, 405, 405, 405, 405, 405, 133, + 133, 133, 133, 133, 133, 133, 133, 274, 274, 78, 78, 78, 78, 78, 133, + 133, 274, 274, 274, 274, 274, 274, 78, 78, 78, 78, 274, 274, 602, 602, + 694, 694, 694, 602, 64, 64, 514, 514, 64, 64, 64, 64, 64, 64, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 34, 34, 34, 34, 34, 34, 34, 64, 34, 34, 34, 34, 34, + 34, 434, 64, 434, 434, 64, 64, 434, 64, 64, 434, 434, 64, 64, 434, 434, + 434, 434, 64, 434, 434, 34, 34, 64, 34, 64, 34, 34, 34, 34, 34, 34, 34, + 64, 34, 34, 34, 34, 34, 34, 34, 434, 434, 64, 434, 434, 434, 434, 64, 64, + 434, 434, 434, 434, 434, 434, 434, 434, 64, 434, 434, 434, 434, 434, 434, + 434, 64, 34, 34, 434, 434, 64, 434, 434, 434, 434, 64, 434, 434, 434, + 434, 434, 64, 434, 64, 64, 64, 434, 434, 434, 434, 434, 434, 434, 64, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 64, 64, 434, 695, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 437, 34, 34, 34, 34, 34, 34, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 695, 34, 34, 34, 34, 34, 34, 34, 34, 34, 437, + 34, 34, 434, 434, 434, 434, 434, 695, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 437, 34, 34, 34, 34, 34, 34, 434, 434, 434, 434, 434, 434, 434, 434, 434, + 695, 34, 437, 34, 34, 34, 34, 34, 34, 34, 34, 434, 34, 64, 64, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 123, 123, 123, 123, 64, 123, 123, + 123, 64, 123, 123, 64, 123, 64, 64, 123, 64, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 64, 123, 123, 123, 123, 64, 123, 64, 123, 64, + 64, 64, 64, 64, 64, 123, 64, 64, 64, 64, 123, 64, 123, 64, 123, 64, 123, + 123, 123, 64, 123, 64, 123, 64, 123, 64, 123, 64, 123, 123, 123, 123, 64, + 123, 64, 123, 123, 64, 123, 123, 123, 123, 123, 123, 123, 123, 123, 64, + 64, 64, 64, 64, 123, 123, 123, 64, 123, 123, 123, 111, 111, 64, 64, 64, + 64, 64, 64, 33, 33, 33, 64, 64, 64, 64, 64, 445, 445, 445, 445, 445, 445, + 274, 64, 445, 445, 26, 26, 64, 64, 64, 64, 445, 445, 445, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 274, 274, 697, 481, 481, 64, 64, 64, 64, 64, + 481, 481, 481, 64, 64, 64, 64, 64, 481, 64, 64, 64, 64, 64, 64, 64, 481, + 481, 64, 64, 64, 64, 64, 64, 26, 64, 64, 64, 64, 64, 64, 64, 26, 26, 26, + 26, 26, 26, 64, 26, 26, 26, 26, 26, 26, 64, 64, 64, 26, 26, 26, 26, 26, + 64, 26, 26, 26, 64, 26, 26, 26, 26, 26, 26, 64, 26, 26, 26, 26, 64, 64, + 64, 26, 26, 26, 26, 26, 26, 64, 64, 64, 64, 64, 26, 26, 26, 26, 26, 26, + 64, 64, 64, 64, 26, 26, 26, 489, 489, 489, 489, 489, 489, 488, 490, 490, + 490, 490, 490, 490, 490, 64, 64, 64, 405, 64, 64, 64, 64, 64, 64, 405, + 405, 405, 405, 405, 405, 405, 405, 561, 561, 561, 561, 561, 560, 64, 64, + ]; +} diff --git a/src/vendor/mpdf/mpdf/src/Utils/Arrays.php b/src/vendor/mpdf/mpdf/src/Utils/Arrays.php new file mode 100644 index 000000000..3c9c3d5a4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Utils/Arrays.php @@ -0,0 +1,100 @@ +<?php + +namespace Mpdf\Utils; + +class Arrays +{ + + public static function get($array, $key, $default = null) + { + if (is_array($array) && array_key_exists($key, $array)) { + return $array[$key]; + } + + if (func_num_args() < 3) { + throw new \InvalidArgumentException(sprintf('Array does not contain key "%s"', $key)); + } + + return $default; + } + + /** + * Returns an array of all k-combinations from an input array of n elements, where k equals 1..n. + * Elements will be sorted and unique in every combination. + * + * Example: array[one, two] will give: + * [ + * [one], + * [two], + * [one, two] + * ] + * @param array $array + * @return array + */ + public static function allUniqueSortedCombinations($array) + { + $input = array_unique($array); + if (count($input) <= 1) { + return [$input]; + } + + sort($input); + $combinations = []; + foreach ($input as $value) { + $combinations[] = [$value]; + } + + $n = count($input); + for ($k = 2; $k <= $n; $k++) { + $combinations = array_merge($combinations, self::combinations($input, $k)); + } + + return $combinations; + } + + /** + * Returns an array of unique k-combinations from an input array. + * + * Example: array=[one, two, three] and k=2 will give: + * [ + * [one, two], + * [one, three] + * ] + * @param array $array + * @param int $k + * @return array + */ + public static function combinations($array, $k) + { + $n = count($array); + $combinations = []; + $indexes = range(0, $k - 1); + $maxIndexes = range($n - $k, $n - 1); + do { + $combination = []; + foreach ($indexes as $index) { + $combination[] = $array[$index]; + } + $combinations[] = $combination; + + $anotherCombination = false; + $resetFromIndex = -1; + for ($i = $k - 1; $i >= 0; $i--) { + if ($indexes[$i] < $maxIndexes[$i]) { + $indexes[$i]++; + $anotherCombination = true; + break; + } + $resetFromIndex = $i; + } + + if ($resetFromIndex > 0) { + for ($i = $resetFromIndex; $i < $k; $i++) { + $indexes[$i] = $indexes[$i - 1] + 1; + } + } + } while ($anotherCombination); + + return $combinations; + } +} diff --git a/src/vendor/mpdf/mpdf/src/Utils/NumericString.php b/src/vendor/mpdf/mpdf/src/Utils/NumericString.php new file mode 100644 index 000000000..db10287d3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Utils/NumericString.php @@ -0,0 +1,18 @@ +<?php + +namespace Mpdf\Utils; + +class NumericString +{ + + public static function containsPercentChar($string) + { + return strstr($string, '%'); + } + + public static function removePercentChar($string) + { + return str_replace('%', '', $string); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Utils/PdfDate.php b/src/vendor/mpdf/mpdf/src/Utils/PdfDate.php new file mode 100644 index 000000000..1fc390058 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Utils/PdfDate.php @@ -0,0 +1,30 @@ +<?php + +namespace Mpdf\Utils; + +class PdfDate +{ + + /** + * PDF documents use the internal date format: (D:YYYYMMDDHHmmSSOHH'mm'). The date format has these parts: + * + * YYYY The full four-digit year. (For example, 2004) + * MM The month from 01 to 12. + * DD The day from 01 to 31. + * HH The hour from 00 to 23. + * mm The minute from 00 to 59. + * SS The seconds from 00 to 59. + * O The relationship of local time to Universal Time (UT), as denoted by one of the characters +, -, or Z. + * HH The absolute value of the offset from UT in hours specified as 00 to 23. + * mm The absolute value of the offset from UT in minutes specified as 00 to 59. + * + * @return string + */ + public static function format($date) + { + $z = date('O'); // +0200 + $offset = substr($z, 0, 3) . "'" . substr($z, 3, 2) . "'"; // +02'00' + return date('YmdHis', $date) . $offset; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Utils/UtfString.php b/src/vendor/mpdf/mpdf/src/Utils/UtfString.php new file mode 100644 index 000000000..2bf9c5738 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Utils/UtfString.php @@ -0,0 +1,69 @@ +<?php + +namespace Mpdf\Utils; + +class UtfString +{ + + /** + * Converts all the &#nnn; and &#xhhh; in a string to Unicode + * + * @since mPDF 5.7 + * @param string $str + * @param bool $lo + * + * @return string + */ + public static function strcode2utf($str, $lo = true) + { + $str = preg_replace_callback('/\&\#(\d+)\;/m', function ($matches) use ($lo) { + return static::code2utf($matches[1], $lo ? 1 : 0); + }, $str); + $str = preg_replace_callback('/\&\#x([0-9a-fA-F]+)\;/m', function ($matches) use ($lo) { + return static::codeHex2utf($matches[1], $lo ? 1 : 0); + }, $str); + + return $str; + } + + /** + * @param int $num + * @param bool $lo + * + * @return string + */ + public static function code2utf($num, $lo = true) + { + // Returns the utf string corresponding to the unicode value + if ($num < 128) { + return $lo + ? chr($num) + : '&#' . $num . ';'; + } + + if ($num < 2048) { + return chr(($num >> 6) + 192) . chr(($num & 63) + 128); + } + + if ($num < 65536) { + return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128); + } + + if ($num < 2097152) { + return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128); + } + + return '?'; + } + + public static function codeHex2utf($hex, $lo = true) + { + $num = hexdec($hex); + if (($num < 128) && !$lo) { + return '&#x' . $hex . ';'; + } + + return static::code2utf($num, $lo); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Watermark.php b/src/vendor/mpdf/mpdf/src/Watermark.php new file mode 100644 index 000000000..4d908de37 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Watermark.php @@ -0,0 +1,8 @@ +<?php + +namespace Mpdf; + +interface Watermark +{ + +} diff --git a/src/vendor/mpdf/mpdf/src/WatermarkImage.php b/src/vendor/mpdf/mpdf/src/WatermarkImage.php new file mode 100644 index 000000000..1c62b8823 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/WatermarkImage.php @@ -0,0 +1,72 @@ +<?php + +namespace Mpdf; + +class WatermarkImage implements \Mpdf\Watermark +{ + + const SIZE_DEFAULT = 'D'; + const SIZE_FIT_PAGE = 'P'; + const SIZE_FIT_FRAME = 'F'; + const POSITION_CENTER_PAGE = 'P'; + const POSITION_CENTER_FRAME = 'F'; + + /** @var string */ + private $path; + + /** @var mixed */ + private $size; + + /** @var mixed */ + private $position; + + /** @var float */ + private $alpha; + + /** @var bool */ + private $behindContent; + + /** @var string */ + private $alphaBlend; + + public function __construct($path, $size = self::SIZE_DEFAULT, $position = self::POSITION_CENTER_PAGE, $alpha = -1, $behindContent = false, $alphaBlend = 'Normal') + { + $this->path = $path; + $this->size = $size; + $this->position = $position; + $this->alpha = $alpha; + $this->behindContent = $behindContent; + $this->alphaBlend = $alphaBlend; + } + + public function getPath() + { + return $this->path; + } + + public function getSize() + { + return $this->size; + } + + public function getPosition() + { + return $this->position; + } + + public function getAlpha() + { + return $this->alpha; + } + + public function isBehindContent() + { + return $this->behindContent; + } + + public function getAlphaBlend() + { + return $this->alphaBlend; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/WatermarkText.php b/src/vendor/mpdf/mpdf/src/WatermarkText.php new file mode 100644 index 000000000..1e1129b2d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/WatermarkText.php @@ -0,0 +1,66 @@ +<?php + +namespace Mpdf; + +class WatermarkText implements \Mpdf\Watermark +{ + + /** @var string */ + private $text; + + /** @var int */ + private $size; + + /** @var int */ + private $angle; + + /** @var mixed */ + private $color; + + /** @var float */ + private $alpha; + + /** @var string */ + private $font; + + public function __construct($text, $size = 96, $angle = 45, $color = 0, $alpha = 0.2, $font = null) + { + $this->text = $text; + $this->size = $size; + $this->angle = $angle; + $this->color = $color; + $this->alpha = $alpha; + $this->font = $font; + } + + public function getText() + { + return $this->text; + } + + public function getSize() + { + return $this->size; + } + + public function getAngle() + { + return $this->angle; + } + + public function getColor() + { + return $this->color; + } + + public function getAlpha() + { + return $this->alpha; + } + + public function getFont() + { + return $this->font; + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/BackgroundWriter.php b/src/vendor/mpdf/mpdf/src/Writer/BackgroundWriter.php new file mode 100644 index 000000000..6dbce84d3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/BackgroundWriter.php @@ -0,0 +1,451 @@ +<?php + +namespace Mpdf\Writer; + +use Mpdf\Strict; +use Mpdf\Mpdf; + +final class BackgroundWriter +{ + + use Strict; + + /** + * @var \Mpdf\Mpdf + */ + private $mpdf; + + /** + * @var \Mpdf\Writer\BaseWriter + */ + private $writer; + + public function __construct(Mpdf $mpdf, BaseWriter $writer) + { + $this->mpdf = $mpdf; + $this->writer = $writer; + } + + public function writePatterns() // _putpatterns + { + $patternCount = count($this->mpdf->patterns); + + for ($i = 1; $i <= $patternCount; $i++) { + + $x = $this->mpdf->patterns[$i]['x']; + $y = $this->mpdf->patterns[$i]['y']; + $w = $this->mpdf->patterns[$i]['w']; + $h = $this->mpdf->patterns[$i]['h']; + $pgh = $this->mpdf->patterns[$i]['pgh']; + $orig_w = $this->mpdf->patterns[$i]['orig_w']; + $orig_h = $this->mpdf->patterns[$i]['orig_h']; + $image_id = $this->mpdf->patterns[$i]['image_id']; + $itype = $this->mpdf->patterns[$i]['itype']; + + if (isset($this->mpdf->patterns[$i]['bpa'])) { + $bpa = $this->mpdf->patterns[$i]['bpa']; + } else { + $bpa = []; // background positioning area + } + + if ($this->mpdf->patterns[$i]['x_repeat']) { + $x_repeat = true; + } else { + $x_repeat = false; + } + + if ($this->mpdf->patterns[$i]['y_repeat']) { + $y_repeat = true; + } else { + $y_repeat = false; + } + + $x_pos = $this->mpdf->patterns[$i]['x_pos']; + + if (false !== strpos($x_pos, '%')) { + $x_pos = (float) $x_pos; + $x_pos /= 100; + + if (isset($bpa['w']) && $bpa['w']) { + $x_pos = ($bpa['w'] * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos); + } else { + $x_pos = ($w * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos); + } + } + + $y_pos = $this->mpdf->patterns[$i]['y_pos']; + + if (false !== strpos($y_pos, '%')) { + $y_pos = (float) $y_pos; + $y_pos /= 100; + + if (isset($bpa['h']) && $bpa['h']) { + $y_pos = ($bpa['h'] * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos); + } else { + $y_pos = ($h * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos); + } + } + + if (isset($bpa['x']) && $bpa['x']) { + $adj_x = ($x_pos + $bpa['x']) * Mpdf::SCALE; + } else { + $adj_x = ($x_pos + $x) * Mpdf::SCALE; + } + + if (isset($bpa['y']) && $bpa['y']) { + $adj_y = (($pgh - $y_pos - $bpa['y']) * Mpdf::SCALE) - $orig_h; + } else { + $adj_y = (($pgh - $y_pos - $y) * Mpdf::SCALE) - $orig_h; + } + + $img_obj = false; + + if ($itype === 'svg' || $itype === 'wmf') { + foreach ($this->mpdf->formobjects as $fo) { + if ($fo['i'] == $image_id) { + $img_obj = $fo['n']; + $fo_w = $fo['w']; + $fo_h = -$fo['h']; + $wmf_x = $fo['x']; + $wmf_y = $fo['y']; + break; + } + } + } else { + foreach ($this->mpdf->images as $img) { + if ($img['i'] == $image_id) { + $img_obj = $img['n']; + break; + } + } + } + + if (!$img_obj) { + throw new \Mpdf\MpdfException('Problem: Image object not found for background pattern ' . $img['i']); + } + + $this->writer->object(); + $this->writer->write('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); + + if ($itype === 'svg' || $itype === 'wmf') { + $this->writer->write('/XObject <</FO' . $image_id . ' ' . $img_obj . ' 0 R >>'); + + // ******* ADD ANY ExtGStates, Shading AND Fonts needed for the FormObject + // Set in classes/svg array['fo'] = true + // Required that _putshaders comes before _putpatterns in _putresources + // This adds any resources associated with any FormObject to every Formobject - overkill but works! + if (count($this->mpdf->extgstates)) { + $this->writer->write('/ExtGState <<'); + foreach ($this->mpdf->extgstates as $k => $extgstate) { + if (isset($extgstate['fo']) && $extgstate['fo']) { + if (isset($extgstate['trans'])) { + $this->writer->write('/' . $extgstate['trans'] . ' ' . $extgstate['n'] . ' 0 R'); + } else { + $this->writer->write('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R'); + } + } + } + $this->writer->write('>>'); + } + + /* -- BACKGROUNDS -- */ + if (isset($this->mpdf->gradients) && ( count($this->mpdf->gradients) > 0)) { + $this->writer->write('/Shading <<'); + foreach ($this->mpdf->gradients as $id => $grad) { + if (isset($grad['fo']) && $grad['fo']) { + $this->writer->write('/Sh' . $id . ' ' . $grad['id'] . ' 0 R'); + } + } + $this->writer->write('>>'); + } + + /* -- END BACKGROUNDS -- */ + $this->writer->write('/Font <<'); + + foreach ($this->mpdf->fonts as $font) { + if (!$font['used'] && $font['type'] === 'TTF') { + continue; + } + if (isset($font['fo']) && $font['fo']) { + if ($font['type'] === 'TTF' && ($font['sip'] || $font['smp'])) { + foreach ($font['n'] as $k => $fid) { + $this->writer->write('/F' . $font['subsetfontids'][$k] . ' ' . $font['n'][$k] . ' 0 R'); + } + } else { + $this->writer->write('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + } + } + } + $this->writer->write('>>'); + } else { + $this->writer->write('/XObject <</I' . $image_id . ' ' . $img_obj . ' 0 R >>'); + } + + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $this->writer->object(); + $this->mpdf->patterns[$i]['n'] = $this->mpdf->n; + $this->writer->write('<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 2'); + $this->writer->write('/Resources ' . ($this->mpdf->n - 1) . ' 0 R'); + + $this->writer->write(sprintf('/BBox [0 0 %.3F %.3F]', $orig_w, $orig_h)); + + if ($x_repeat) { + $this->writer->write(sprintf('/XStep %.3F', $orig_w)); + } else { + $this->writer->write(sprintf('/XStep %d', 99999)); + } + + if ($y_repeat) { + $this->writer->write(sprintf('/YStep %.3F', $orig_h)); + } else { + $this->writer->write(sprintf('/YStep %d', 99999)); + } + + if ($itype === 'svg' || $itype === 'wmf') { + $this->writer->write(sprintf('/Matrix [1 0 0 -1 %.3F %.3F]', $adj_x, $adj_y + $orig_h)); + $s = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $orig_w / $fo_w, -$orig_h / $fo_h, -($orig_w / $fo_w) * $wmf_x, ($orig_w / $fo_w) * $wmf_y, $image_id); + } else { + $this->writer->write(sprintf('/Matrix [1 0 0 1 %.3F %.3F]', $adj_x, $adj_y)); + $s = sprintf('q %.3F 0 0 %.3F 0 0 cm /I%d Do Q', $orig_w, $orig_h, $image_id); + } + + if ($this->mpdf->compress) { + $this->writer->write('/Filter /FlateDecode'); + $s = gzcompress($s); + } + $this->writer->write('/Length ' . strlen($s) . '>>'); + $this->writer->stream($s); + $this->writer->write('endobj'); + } + } + + public function writeShaders() // _putshaders + { + $maxid = count($this->mpdf->gradients); // index for transparency gradients + + foreach ($this->mpdf->gradients as $id => $grad) { + + if (empty($grad['is_mask']) && ($grad['type'] == 2 || $grad['type'] == 3)) { + + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/FunctionType 3'); + $this->writer->write('/Domain [0 1]'); + + $fn = []; + $bd = []; + $en = []; + + for ($i = 0; $i < (count($grad['stops']) - 1); $i++) { + $fn[] = ($this->mpdf->n + 1 + $i) . ' 0 R'; + $en[] = '0 1'; + if ($i > 0) { + $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); + } + } + + $this->writer->write('/Functions [' . implode(' ', $fn) . ']'); + $this->writer->write('/Bounds [' . implode(' ', $bd) . ']'); + $this->writer->write('/Encode [' . implode(' ', $en) . ']'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $f1 = $this->mpdf->n; + + for ($i = 0; $i < (count($grad['stops']) - 1); $i++) { + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/FunctionType 2'); + $this->writer->write('/Domain [0 1]'); + $this->writer->write('/C0 [' . $grad['stops'][$i]['col'] . ']'); + $this->writer->write('/C1 [' . $grad['stops'][$i + 1]['col'] . ']'); + $this->writer->write('/N 1'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + } + + if ($grad['type'] == 2 || $grad['type'] == 3) { + + if (isset($grad['trans']) && $grad['trans']) { + + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/FunctionType 3'); + $this->writer->write('/Domain [0 1]'); + + $fn = []; + $bd = []; + $en = []; + + for ($i = 0; $i < (count($grad['stops']) - 1); $i++) { + $fn[] = ($this->mpdf->n + 1 + $i) . ' 0 R'; + $en[] = '0 1'; + if ($i > 0) { + $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']); + } + } + + $this->writer->write('/Functions [' . implode(' ', $fn) . ']'); + $this->writer->write('/Bounds [' . implode(' ', $bd) . ']'); + $this->writer->write('/Encode [' . implode(' ', $en) . ']'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $f2 = $this->mpdf->n; + + for ($i = 0; $i < (count($grad['stops']) - 1); $i++) { + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/FunctionType 2'); + $this->writer->write('/Domain [0 1]'); + $this->writer->write(sprintf('/C0 [%.3F]', $grad['stops'][$i]['opacity'])); + $this->writer->write(sprintf('/C1 [%.3F]', $grad['stops'][$i + 1]['opacity'])); + $this->writer->write('/N 1'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + } + } + + if (empty($grad['is_mask'])) { + + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/ShadingType ' . $grad['type']); + + if (isset($grad['colorspace'])) { + $this->writer->write('/ColorSpace /Device' . $grad['colorspace']); // Can use CMYK if all C0 and C1 above have 4 values + } else { + $this->writer->write('/ColorSpace /DeviceRGB'); + } + + if ($grad['type'] == 2) { + $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3])); + $this->writer->write('/Function ' . $f1 . ' 0 R'); + $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] '); + $this->writer->write('>>'); + } elseif ($grad['type'] == 3) { + // x0, y0, r0, x1, y1, r1 + // at this this time radius of inner circle is 0 + $ir = 0; + if (isset($grad['coords'][5]) && $grad['coords'][5]) { + $ir = $grad['coords'][5]; + } + $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4])); + $this->writer->write('/Function ' . $f1 . ' 0 R'); + $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] '); + $this->writer->write('>>'); + } elseif ($grad['type'] == 6) { + $this->writer->write('/BitsPerCoordinate 16'); + $this->writer->write('/BitsPerComponent 8'); + if ($grad['colorspace'] === 'CMYK') { + $this->writer->write('/Decode[0 1 0 1 0 1 0 1 0 1 0 1]'); + } elseif ($grad['colorspace'] === 'Gray') { + $this->writer->write('/Decode[0 1 0 1 0 1]'); + } else { + $this->writer->write('/Decode[0 1 0 1 0 1 0 1 0 1]'); + } + $this->writer->write('/BitsPerFlag 8'); + $this->writer->write('/Length ' . strlen($grad['stream'])); + $this->writer->write('>>'); + $this->writer->stream($grad['stream']); + } + + $this->writer->write('endobj'); + } + + $this->mpdf->gradients[$id]['id'] = $this->mpdf->n; + + // set pattern object + $this->writer->object(); + $out = '<< /Type /Pattern /PatternType 2'; + $out .= ' /Shading ' . $this->mpdf->gradients[$id]['id'] . ' 0 R'; + $out .= ' >>'; + $out .= "\n" . 'endobj'; + $this->writer->write($out); + + + $this->mpdf->gradients[$id]['pattern'] = $this->mpdf->n; + + if (isset($grad['trans']) && $grad['trans']) { + + // luminosity pattern + $transid = $id + $maxid; + + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/ShadingType ' . $grad['type']); + $this->writer->write('/ColorSpace /DeviceGray'); + + if ($grad['type'] == 2) { + $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3])); + $this->writer->write('/Function ' . $f2 . ' 0 R'); + $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] '); + $this->writer->write('>>'); + } elseif ($grad['type'] == 3) { + // x0, y0, r0, x1, y1, r1 + // at this this time radius of inner circle is 0 + $ir = 0; + if (isset($grad['coords'][5]) && $grad['coords'][5]) { + $ir = $grad['coords'][5]; + } + $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4])); + $this->writer->write('/Function ' . $f2 . ' 0 R'); + $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] '); + $this->writer->write('>>'); + } elseif ($grad['type'] == 6) { + $this->writer->write('/BitsPerCoordinate 16'); + $this->writer->write('/BitsPerComponent 8'); + $this->writer->write('/Decode[0 1 0 1 0 1]'); + $this->writer->write('/BitsPerFlag 8'); + $this->writer->write('/Length ' . strlen($grad['stream_trans'])); + $this->writer->write('>>'); + $this->writer->stream($grad['stream_trans']); + } + $this->writer->write('endobj'); + + $this->mpdf->gradients[$transid]['id'] = $this->mpdf->n; + + $this->writer->object(); + $this->writer->write('<< /Type /Pattern /PatternType 2'); + $this->writer->write('/Shading ' . $this->mpdf->gradients[$transid]['id'] . ' 0 R'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $this->mpdf->gradients[$transid]['pattern'] = $this->mpdf->n; + $this->writer->object(); + + // Need to extend size of viewing box in case of transformations + $str = 'q /a0 gs /Pattern cs /p' . $transid . ' scn -' . ($this->mpdf->wPt / 2) . ' -' . ($this->mpdf->hPt / 2) . ' ' . (2 * $this->mpdf->wPt) . ' ' . (2 * $this->mpdf->hPt) . ' re f Q'; + $filter = ($this->mpdf->compress) ? '/Filter /FlateDecode ' : ''; + $p = ($this->mpdf->compress) ? gzcompress($str) : $str; + + $this->writer->write('<< /Type /XObject /Subtype /Form /FormType 1 ' . $filter); + $this->writer->write('/Length ' . strlen($p)); + $this->writer->write('/BBox [-' . ($this->mpdf->wPt / 2) . ' -' . ($this->mpdf->hPt / 2) . ' ' . (2 * $this->mpdf->wPt) . ' ' . (2 * $this->mpdf->hPt) . ']'); + $this->writer->write('/Group << /Type /Group /S /Transparency /CS /DeviceGray >>'); + $this->writer->write('/Resources <<'); + $this->writer->write('/ExtGState << /a0 << /ca 1 /CA 1 >> >>'); + $this->writer->write('/Pattern << /p' . $transid . ' ' . $this->mpdf->gradients[$transid]['pattern'] . ' 0 R >>'); + $this->writer->write('>>'); + $this->writer->write('>>'); + $this->writer->stream($p); + $this->writer->write('endobj'); + $this->writer->object(); + $this->writer->write('<< /Type /Mask /S /Luminosity /G ' . ($this->mpdf->n - 1) . ' 0 R >>' . "\n" . 'endobj'); + $this->writer->object(); + $this->writer->write('<< /Type /ExtGState /SMask ' . ($this->mpdf->n - 1) . ' 0 R /AIS false >>' . "\n" . 'endobj'); + + if (isset($grad['fo']) && $grad['fo']) { + $this->mpdf->extgstates[] = ['n' => $this->mpdf->n, 'trans' => 'TGS' . $id, 'fo' => true]; + } else { + $this->mpdf->extgstates[] = ['n' => $this->mpdf->n, 'trans' => 'TGS' . $id]; + } + } + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/BaseWriter.php b/src/vendor/mpdf/mpdf/src/Writer/BaseWriter.php new file mode 100644 index 000000000..80463f8f1 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/BaseWriter.php @@ -0,0 +1,249 @@ +<?php + +namespace Mpdf\Writer; + +use Mpdf\Strict; +use Mpdf\Mpdf; +use Mpdf\Pdf\Protection; + +final class BaseWriter +{ + + use Strict; + + /** + * @var \Mpdf\Mpdf + */ + private $mpdf; + + /** + * @var \Mpdf\Pdf\Protection + */ + private $protection; + + public function __construct(Mpdf $mpdf, Protection $protection) + { + $this->mpdf = $mpdf; + $this->protection = $protection; + } + + public function write($s, $ln = true) + { + if ($this->mpdf->state === 2) { + $this->endPage($s, $ln); + } else { + $this->mpdf->buffer .= $s . ($ln ? "\n" : ''); + } + } + + public function string($s) + { + if ($this->mpdf->encrypted) { + $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->currentObjectNumber), $s); + } + + return '(' . $this->escape($s) . ')'; + } + + public function object($obj_id = false, $onlynewobj = false) + { + if (!$obj_id) { + $obj_id = ++$this->mpdf->n; + } + + // Begin a new object + if (!$onlynewobj) { + $this->mpdf->offsets[$obj_id] = strlen($this->mpdf->buffer); + $this->write($obj_id . ' 0 obj'); + $this->mpdf->currentObjectNumber = $obj_id; // for later use with encryption + } + } + + public function stream($s) + { + if ($this->mpdf->encrypted) { + $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->currentObjectNumber), $s); + } + + $this->write('stream'); + $this->write($s); + $this->write('endstream'); + } + + public function utf16BigEndianTextString($s) // _UTF16BEtextstring + { + $s = $this->utf8ToUtf16BigEndian($s, true); + if ($this->mpdf->encrypted) { + $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->currentObjectNumber), $s); + } + + return '(' . $this->escape($s) . ')'; + } + + // Converts UTF-8 strings to UTF16-BE. + public function utf8ToUtf16BigEndian($str, $setbom = true) // UTF8ToUTF16BE + { + if ($this->mpdf->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) { + if (!in_array($this->mpdf->currentfontfamily, ['gb', 'big5', 'sjis', 'uhc', 'gbB', 'big5B', 'sjisB', 'uhcB', 'gbI', 'big5I', 'sjisI', 'uhcI', + 'gbBI', 'big5BI', 'sjisBI', 'uhcBI'])) { + $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str); + } + } + if ($this->mpdf->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str)) { + $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str); + } + + $outstr = ''; // string to be returned + if ($setbom) { + $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM) + } + + $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8'); + + return $outstr; + } + + public function escape($s) // _escape + { + return strtr($s, [')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r']); + } + + public function escapeSlashes($s) // _escapeName + { + return strtr($s, ['/' => '#2F']); + } + + /** + * Un-escapes a PDF string + * + * @param string $s + * @return string + */ + public function unescape($s) + { + $out = ''; + for ($count = 0, $n = strlen($s); $count < $n; $count++) { + if ($count === $n - 1 || $s[$count] !== '\\') { + $out .= $s[$count]; + } else { + switch ($s[++$count]) { + case ')': + case '(': + case '\\': + $out .= $s[$count]; + break; + case 'f': + $out .= chr(0x0C); + break; + case 'b': + $out .= chr(0x08); + break; + case 't': + $out .= chr(0x09); + break; + case 'r': + $out .= chr(0x0D); + break; + case 'n': + $out .= chr(0x0A); + break; + case "\r": + if ($count !== $n - 1 && $s[$count + 1] === "\n") { + $count++; + } + break; + case "\n": + break; + default: + // Octal-Values + $ord = ord($s[$count]); + if ($ord >= ord('0') && $ord <= ord('9')) { + $oct = ''. $s[$count]; + $ord = ord($s[$count + 1]); + if ($ord >= ord('0') && $ord <= ord('9')) { + $oct .= $s[++$count]; + $ord = ord($s[$count + 1]); + if ($ord >= ord('0') && $ord <= ord('9')) { + $oct .= $s[++$count]; + } + } + $out .= chr(octdec($oct)); + } else { + $out .= $s[$count]; + } + } + } + } + + return $out; + } + + private function endPage($s, $ln) + { + if ($this->mpdf->bufferoutput) { + + $this->mpdf->headerbuffer.= $s . "\n"; + + } elseif ($this->mpdf->ColActive && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) { + + // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except: + // Images sent from Image() or + // later sent as write($textto) in printbuffer + // Line() + + if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/', $s, $m)) { // Image data + + $h = ($m[1] / Mpdf::SCALE); + // Update/overwrite the lowest bottom of printing y value for a column + $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] = $this->mpdf->y + $h; + + } elseif ($this->mpdf->tableLevel > 0 && preg_match('/\d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ ([\-]{0,1}\d+\.\d\d+) re/', $s, $m)) { // Rect in table + + $h = ($m[1] / Mpdf::SCALE); + // Update/overwrite the lowest bottom of printing y value for a column + $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] = max($this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'], $this->mpdf->y + $h); + + } elseif (isset($this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'])) { + + $h = $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] - $this->mpdf->y; + + } else { + + $h = 0; + + } + + if ($h < 0) { + $h = -$h; + } + + $this->mpdf->columnbuffer[] = [ + 's' => $s, // Text string to output + 'col' => $this->mpdf->CurrCol, // Column when printed + 'x' => $this->mpdf->x, // x when printed + 'y' => $this->mpdf->y, // this->y when printed (after column break) + 'h' => $h // actual y at bottom when printed = y+h + ]; + + } elseif ($this->mpdf->table_rotate && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) { + + // Captures eveything in buffer for rotated tables; + $this->mpdf->tablebuffer .= $s . "\n"; + + } elseif ($this->mpdf->kwt && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) { + + // Captures eveything in buffer for keep-with-table (h1-6); + $this->mpdf->kwt_buffer[] = [ + 's' => $s, // Text string to output + 'x' => $this->mpdf->x, // x when printed + 'y' => $this->mpdf->y, // y when printed + ]; + + } elseif ($this->mpdf->keep_block_together && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) { + // do nothing + } else { + $this->mpdf->pages[$this->mpdf->page] .= $s . ($ln ? "\n" : ''); + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/BookmarkWriter.php b/src/vendor/mpdf/mpdf/src/Writer/BookmarkWriter.php new file mode 100644 index 000000000..bbec0d767 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/BookmarkWriter.php @@ -0,0 +1,138 @@ +<?php + +namespace Mpdf\Writer; + +use Mpdf\Strict; +use Mpdf\Mpdf; + +final class BookmarkWriter +{ + + use Strict; + + /** + * @var \Mpdf\Mpdf + */ + private $mpdf; + + /** + * @var \Mpdf\Writer\BaseWriter + */ + private $writer; + + public function __construct(Mpdf $mpdf, BaseWriter $writer) + { + $this->mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeBookmarks() // _putbookmarks + { + $nb = count($this->mpdf->BMoutlines); + if ($nb === 0) { + return; + } + + $bmo = $this->mpdf->BMoutlines; + $this->mpdf->BMoutlines = []; + $lastlevel = -1; + for ($i = 0; $i < count($bmo); $i++) { + if ($bmo[$i]['l'] > 0) { + while ($bmo[$i]['l'] - $lastlevel > 1) { // If jump down more than one level, insert a new entry + $new = $bmo[$i]; + $new['t'] = "[" . $new['t'] . "]"; // Put [] around text/title to highlight + $new['l'] = $lastlevel + 1; + $lastlevel++; + $this->mpdf->BMoutlines[] = $new; + } + } + $this->mpdf->BMoutlines[] = $bmo[$i]; + $lastlevel = $bmo[$i]['l']; + } + $nb = count($this->mpdf->BMoutlines); + + $lru = []; + $level = 0; + foreach ($this->mpdf->BMoutlines as $i => $o) { + if ($o['l'] > 0) { + $parent = $lru[$o['l'] - 1]; + // Set parent and last pointers + $this->mpdf->BMoutlines[$i]['parent'] = $parent; + $this->mpdf->BMoutlines[$parent]['last'] = $i; + if ($o['l'] > $level) { + // Level increasing: set first pointer + $this->mpdf->BMoutlines[$parent]['first'] = $i; + } + } else { + $this->mpdf->BMoutlines[$i]['parent'] = $nb; + } + if ($o['l'] <= $level and $i > 0) { + // Set prev and next pointers + $prev = $lru[$o['l']]; + $this->mpdf->BMoutlines[$prev]['next'] = $i; + $this->mpdf->BMoutlines[$i]['prev'] = $prev; + } + $lru[$o['l']] = $i; + $level = $o['l']; + } + + + // Outline items + $n = $this->mpdf->n + 1; + foreach ($this->mpdf->BMoutlines as $i => $o) { + $this->writer->object(); + $this->writer->write('<writer->utf16BigEndianTextString($o['t'])); + $this->writer->write('/Parent ' . ($n + $o['parent']) . ' 0 R'); + if (isset($o['prev'])) { + $this->writer->write('/Prev ' . ($n + $o['prev']) . ' 0 R'); + } + if (isset($o['next'])) { + $this->writer->write('/Next ' . ($n + $o['next']) . ' 0 R'); + } + if (isset($o['first'])) { + $this->writer->write('/First ' . ($n + $o['first']) . ' 0 R'); + } + if (isset($o['last'])) { + $this->writer->write('/Last ' . ($n + $o['last']) . ' 0 R'); + } + + + if (isset($this->mpdf->pageDim[$o['p']]['h'])) { + $h = $this->mpdf->pageDim[$o['p']]['h']; + } else { + $h = 0; + } + + $this->writer->write(sprintf('/Dest [%d 0 R /XYZ 0 %.3F null]', 1 + 2 * ($o['p']), ($h - $o['y']) * Mpdf::SCALE)); + if (isset($this->mpdf->bookmarkStyles) && isset($this->mpdf->bookmarkStyles[$o['l']])) { + // font style + $bms = $this->mpdf->bookmarkStyles[$o['l']]['style']; + $style = 0; + if (strpos($bms, 'B') !== false) { + $style += 2; + } + if (strpos($bms, 'I') !== false) { + $style += 1; + } + $this->writer->write(sprintf('/F %d', $style)); + // Colour + $col = $this->mpdf->bookmarkStyles[$o['l']]['color']; + if (isset($col) && is_array($col) && count($col) == 3) { + $this->writer->write(sprintf('/C [%.3F %.3F %.3F]', ($col[0] / 255), ($col[1] / 255), ($col[2] / 255))); + } + } + + $this->writer->write('/Count 0>>'); + $this->writer->write('endobj'); + } + // Outline root + $this->writer->object(); + + $this->mpdf->OutlineRoot = $this->mpdf->n; + + $this->writer->write('<writer->write('/Last ' . ($n + $lru[0]) . ' 0 R>>'); + $this->writer->write('endobj'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/ColorWriter.php b/src/vendor/mpdf/mpdf/src/Writer/ColorWriter.php new file mode 100644 index 000000000..c6ece981b --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/ColorWriter.php @@ -0,0 +1,46 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeSpotColors() // _putspotcolors + { + foreach ($this->mpdf->spotColors as $name => $color) { + + $this->writer->object(); + + $this->writer->write('[/Separation /' . str_replace(' ', '#20', $name)); + $this->writer->write('/DeviceCMYK <<'); + $this->writer->write('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] '); + $this->writer->write(sprintf('/C1 [%.3F %.3F %.3F %.3F] ', $color['c'] / 100, $color['m'] / 100, $color['y'] / 100, $color['k'] / 100)); + $this->writer->write('/FunctionType 2 /Domain [0 1] /N 1>>]'); + $this->writer->write('endobj'); + + $this->mpdf->spotColors[$name]['n'] = $this->mpdf->n; + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/FontWriter.php b/src/vendor/mpdf/mpdf/src/Writer/FontWriter.php new file mode 100644 index 000000000..ddc70232d --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/FontWriter.php @@ -0,0 +1,679 @@ +mpdf = $mpdf; + $this->writer = $writer; + $this->fontCache = $fontCache; + $this->fontDescriptor = $fontDescriptor; + } + + public function writeFonts() + { + foreach ($this->mpdf->FontFiles as $fontkey => $info) { + // TrueType embedded + if (isset($info['type']) && $info['type'] === 'TTF' && !$info['sip'] && !$info['smp']) { + $used = true; + $asSubset = false; + foreach ($this->mpdf->fonts as $k => $f) { + if (isset($f['fontkey']) && $f['fontkey'] === $fontkey && $f['type'] === 'TTF') { + $used = $f['used']; + if ($used) { + $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]); + $usage = (int) (count($f['subset']) * 100 / $nChars); + $fsize = $info['length1']; + // Always subset the very large TTF files + if ($fsize > ($this->mpdf->maxTTFFilesize * 1024)) { + $asSubset = true; + } elseif ($usage < $this->mpdf->percentSubset) { + $asSubset = true; + } + } + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { + $asSubset = false; + } + $this->mpdf->fonts[$k]['asSubset'] = $asSubset; + break; + } + } + if ($used && !$asSubset) { + // Font file embedding + $this->writer->object(); + $this->mpdf->FontFiles[$fontkey]['n'] = $this->mpdf->n; + $originalsize = $info['length1']; + if ($this->mpdf->repackageTTF || $this->mpdf->fonts[$fontkey]['TTCfontID'] > 0 || $this->mpdf->fonts[$fontkey]['useOTL'] > 0) { // mPDF 5.7.1 + // First see if there is a cached compressed file + if ($this->fontCache->has($fontkey . '.ps.z') && $this->fontCache->jsonHas($fontkey . '.ps.json')) { + $font = $this->fontCache->load($fontkey . '.ps.z'); + $originalsize = $this->fontCache->jsonLoad($fontkey . '.ps.json'); // sets $originalsize (of repackaged font) + } else { + $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor); + $font = $ttf->repackageTTF($this->mpdf->FontFiles[$fontkey]['ttffile'], $this->mpdf->fonts[$fontkey]['TTCfontID'], $this->mpdf->debugfonts, $this->mpdf->fonts[$fontkey]['useOTL']); // mPDF 5.7.1 + + $originalsize = strlen($font); + $font = gzcompress($font); + unset($ttf); + + $this->fontCache->binaryWrite($fontkey . '.ps.z', $font); + $this->fontCache->jsonWrite($fontkey . '.ps.json', $originalsize); + } + } elseif ($this->fontCache->has($fontkey . '.z')) { + $font = $this->fontCache->load($fontkey . '.z'); + } else { + $font = file_get_contents($this->mpdf->FontFiles[$fontkey]['ttffile']); + $font = gzcompress($font); + $this->fontCache->binaryWrite($fontkey . '.z', $font); + } + + $this->writer->write('<writer->write('/Filter /FlateDecode'); + $this->writer->write('/Length1 ' . $originalsize); + $this->writer->write('>>'); + $this->writer->stream($font); + $this->writer->write('endobj'); + } + } + } + + foreach ($this->mpdf->fonts as $k => $font) { + + // Font objects + $type = $font['type']; + $name = $font['name']; + + if ($type === 'TTF' && (!isset($font['used']) || !$font['used'])) { + continue; + } + + // @log Writing fonts + + if (isset($font['asSubset'])) { + $asSubset = $font['asSubset']; + } else { + $asSubset = ''; + } + + if ($type === 'Type0') { // Adobe CJK Fonts + + $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1; + $this->writer->object(); + $this->writer->write('<writeType0($font); + + } elseif ($type === 'core') { + + // Standard font + $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1; + + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { + throw new \Mpdf\MpdfException('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)'); + } + + $this->writer->object(); + $this->writer->write('<writer->write('/BaseFont /' . $name); + $this->writer->write('/Subtype /Type1'); + + if ($name !== 'Symbol' && $name !== 'ZapfDingbats') { + $this->writer->write('/Encoding /WinAnsiEncoding'); + } + + $this->writer->write('>>'); + $this->writer->write('endobj'); + + } elseif ($type === 'TTF' && ($font['sip'] || $font['smp'])) { + + // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2) + // Or Unicode Plane 1 - Supplementary Multilingual Plane + + if (!$font['used']) { + continue; + } + + $ssfaid = 'AA'; + $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor); + $subsetCount = count($font['subsetfontids']); + for ($sfid = 0; $sfid < $subsetCount; $sfid++) { + $this->mpdf->fonts[$k]['n'][$sfid] = $this->mpdf->n + 1; // NB an array for subset + $subsetname = 'MPDF' . $ssfaid . '+' . $font['name']; + $ssfaid++; + + /* For some strange reason a subset ($sfid > 0) containing less than 97 characters causes an error + so fill up the array */ + for ($j = count($font['subsets'][$sfid]); $j < 98; $j++) { + $font['subsets'][$sfid][$j] = 0; + } + + $subset = $font['subsets'][$sfid]; + unset($subset[0]); + $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']); // mPDF 5.7.1 + $ttfontsize = strlen($ttfontstream); + $fontstream = gzcompress($ttfontstream); + $widthstring = ''; + $toUnistring = ''; + + foreach ($font['subsets'][$sfid] as $cp => $u) { + $w = $this->mpdf->_getCharWidth($font['cw'], $u); + if ($w !== false) { + $widthstring .= $w . ' '; + } else { + $widthstring .= round($ttf->defaultWidth) . ' '; + } + if ($u > 65535) { + $utf8 = chr(($u >> 18) + 240) . chr((($u >> 12) & 63) + 128) . chr((($u >> 6) & 63) + 128) . chr(($u & 63) + 128); + $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8'); + $l1 = ord($utf16[0]); + $h1 = ord($utf16[1]); + $l2 = ord($utf16[2]); + $h2 = ord($utf16[3]); + $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2))); + } else { + $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u))); + } + } + + // Additional Type1 or TrueType font + $this->writer->object(); + $this->writer->write('<writer->write('/BaseFont /' . $subsetname); + $this->writer->write('/Subtype /TrueType'); + $this->writer->write('/FirstChar 0 /LastChar ' . (count($font['subsets'][$sfid]) - 1)); + $this->writer->write('/Widths ' . ($this->mpdf->n + 1) . ' 0 R'); + $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 2) . ' 0 R'); + $this->writer->write('/ToUnicode ' . ($this->mpdf->n + 3) . ' 0 R'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // Widths + $this->writer->object(); + $this->writer->write('[' . $widthstring . ']'); + $this->writer->write('endobj'); + + // Descriptor + $this->writer->object(); + $s = '< $v) { + if ($kd === 'Flags') { + $v |= 4; + $v &= ~32; + } // SYMBOLIC font flag + $s .= ' /' . $kd . ' ' . $v . "\n"; + } + $s .= '/FontFile2 ' . ($this->mpdf->n + 2) . ' 0 R'; + $this->writer->write($s . '>>'); + $this->writer->write('endobj'); + + // ToUnicode + $this->writer->object(); + $toUni = "/CIDInit /ProcSet findresource begin\n"; + $toUni .= "12 dict begin\n"; + $toUni .= "begincmap\n"; + $toUni .= "/CIDSystemInfo\n"; + $toUni .= "< <%02s>\n", strtoupper(dechex(count($font['subsets'][$sfid])-1))); + $toUni .= "endcodespacerange\n"; + $toUni .= count($font['subsets'][$sfid]) . " beginbfchar\n"; + $toUni .= $toUnistring; + $toUni .= "endbfchar\n"; + $toUni .= "endcmap\n"; + $toUni .= "CMapName currentdict /CMap defineresource pop\n"; + $toUni .= "end\n"; + $toUni .= "end\n"; + $this->writer->write('<>'); + $this->writer->stream($toUni); + $this->writer->write('endobj'); + + // Font file + $this->writer->object(); + $this->writer->write('<writer->write('/Filter /FlateDecode'); + $this->writer->write('/Length1 ' . $ttfontsize); + $this->writer->write('>>'); + $this->writer->stream($fontstream); + $this->writer->write('endobj'); + } // foreach subset + unset($ttf); + + } elseif ($type === 'TTF') { // TrueType embedded SUBSETS or FULL + + $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1; + + if ($asSubset) { + $ssfaid = 'A'; + $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor); + $fontname = 'MPDFA' . $ssfaid . '+' . $font['name']; + $subset = $font['subset']; + unset($subset[0]); + $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']); + $ttfontsize = strlen($ttfontstream); + $fontstream = gzcompress($ttfontstream); + $codeToGlyph = $ttf->codeToGlyph; + unset($codeToGlyph[0]); + } else { + $fontname = $font['name']; + } + + // Type0 Font + // A composite font - a font composed of other fonts, organized hierarchically + $this->writer->object(); + $this->writer->write('<writer->write('/Subtype /Type0'); + $this->writer->write('/BaseFont /' . $fontname . ''); + $this->writer->write('/Encoding /Identity-H'); + $this->writer->write('/DescendantFonts [' . ($this->mpdf->n + 1) . ' 0 R]'); + $this->writer->write('/ToUnicode ' . ($this->mpdf->n + 2) . ' 0 R'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // CIDFontType2 + // A CIDFont whose glyph descriptions are based on TrueType font technology + $this->writer->object(); + $this->writer->write('<writer->write('/Subtype /CIDFontType2'); + $this->writer->write('/BaseFont /' . $fontname . ''); + $this->writer->write('/CIDSystemInfo ' . ($this->mpdf->n + 2) . ' 0 R'); + $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 3) . ' 0 R'); + + if (isset($font['desc']['MissingWidth'])) { + $this->writer->write('/DW ' . $font['desc']['MissingWidth'] . ''); + } + + if (!$asSubset && $this->fontCache->has($font['fontkey'] . '.cw')) { + $w = $this->fontCache->load($font['fontkey'] . '.cw'); + $this->writer->write($w); + } else { + $this->writeTTFontWidths($font, $asSubset, ($asSubset ? $ttf->maxUni : 0)); + } + + $this->writer->write('/CIDToGIDMap ' . ($this->mpdf->n + 4) . ' 0 R'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // ToUnicode + $this->writer->object(); + $toUni = "/CIDInit /ProcSet findresource begin\n"; + $toUni .= "12 dict begin\n"; + $toUni .= "begincmap\n"; + $toUni .= "/CIDSystemInfo\n"; + $toUni .= "<writer->write('<>'); + $this->writer->stream($toUni); + $this->writer->write('endobj'); + + // CIDSystemInfo dictionary + $this->writer->object(); + $this->writer->write('<writer->write('/Ordering (UCS)'); + $this->writer->write('/Supplement 0'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // Font descriptor + $this->writer->object(); + $this->writer->write('<writer->write('/FontName /' . $fontname); + + foreach ($font['desc'] as $kd => $v) { + if ($asSubset && $kd === 'Flags') { + $v |= 4; + $v &= ~32; + } // SYMBOLIC font flag + $this->writer->write(' /' . $kd . ' ' . $v); + } + + if ($font['panose']) { + $this->writer->write(' /Style << /Panose <' . $font['panose'] . '> >>'); + } + + if ($asSubset) { + $this->writer->write('/FontFile2 ' . ($this->mpdf->n + 2) . ' 0 R'); + } elseif ($font['fontkey']) { + // obj ID of a stream containing a TrueType font program + $this->writer->write('/FontFile2 ' . $this->mpdf->FontFiles[$font['fontkey']]['n'] . ' 0 R'); + } + + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // Embed CIDToGIDMap + // A specification of the mapping from CIDs to glyph indices + if ($asSubset) { + $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00"); + foreach ($codeToGlyph as $cc => $glyph) { + $cidtogidmap[$cc * 2] = chr($glyph >> 8); + $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF); + } + $cidtogidmap = gzcompress($cidtogidmap); + } else { + // First see if there is a cached CIDToGIDMapfile + if ($this->fontCache->has($font['fontkey'] . '.cgm')) { + $cidtogidmap = $this->fontCache->load($font['fontkey'] . '.cgm'); + } else { + $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor); + $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']); + $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00"); + foreach ($charToGlyph as $cc => $glyph) { + $cidtogidmap[$cc * 2] = chr($glyph >> 8); + $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF); + } + unset($ttf); + $cidtogidmap = gzcompress($cidtogidmap); + $this->fontCache->binaryWrite($font['fontkey'] . '.cgm', $cidtogidmap); + } + } + $this->writer->object(); + $this->writer->write('<writer->write('/Filter /FlateDecode'); + $this->writer->write('>>'); + $this->writer->stream($cidtogidmap); + $this->writer->write('endobj'); + + // Font file + if ($asSubset) { + $this->writer->object(); + $this->writer->write('<writer->write('/Filter /FlateDecode'); + $this->writer->write('/Length1 ' . $ttfontsize); + $this->writer->write('>>'); + $this->writer->stream($fontstream); + $this->writer->write('endobj'); + unset($ttf); + } + } else { + throw new \Mpdf\MpdfException(sprintf('Unsupported font type: %s (%s)', $type, $name)); + } + } + } + + private function writeTTFontWidths(&$font, $asSubset, $maxUni) // _putTTfontwidths + { + $character = [ + 'startcid' => 1, + 'rangeid' => 0, + 'prevcid' => -2, + 'prevwidth' => -1, + 'interval' => false, + 'range' => [], + ]; + + $fontCacheFilename = $font['fontkey'] . '.cw127.json'; + if ($asSubset && $this->fontCache->jsonHas($fontCacheFilename)) { + $character = $this->fontCache->jsonLoad($fontCacheFilename); + $character['startcid'] = 128; + } + + // for each character + $cwlen = ($asSubset) ? $maxUni + 1 : (strlen($font['cw']) / 2); + for ($cid = $character['startcid']; $cid < $cwlen; $cid++) { + if ($cid == 128 && $asSubset && (!$this->fontCache->has($fontCacheFilename))) { + $character = [ + 'rangeid' => $character['rangeid'], + 'prevcid' => $character['prevcid'], + 'prevwidth' => $character['prevwidth'], + 'interval' => $character['interval'], + 'range' => $character['range'], + ]; + + $this->fontCache->jsonWrite($fontCacheFilename, $character); + } + + $character1 = isset($font['cw'][$cid * 2]) ? $font['cw'][$cid * 2] : ''; + $character2 = isset($font['cw'][$cid * 2 + 1]) ? $font['cw'][$cid * 2 + 1] : ''; + + if ($character1 === "\00" && $character2 === "\00") { + continue; + } + + $width = (ord($character1) << 8) + ord($character2); + + if ($width === 65535) { + $width = 0; + } + + if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) { + continue; + } + + if ($asSubset && $cid > 0xFFFF) { + continue; + } // mPDF 6 + + if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) { + if ($cid === ($character['prevcid'] + 1)) { + // consecutive CID + if ($width === $character['prevwidth']) { + if (isset($character['range'][$character['rangeid']][0]) && $width === $character['range'][$character['rangeid']][0]) { + $character['range'][$character['rangeid']][] = $width; + } else { + array_pop($character['range'][$character['rangeid']]); + // new range + $character['rangeid'] = $character['prevcid']; + $character['range'][$character['rangeid']] = []; + $character['range'][$character['rangeid']][] = $character['prevwidth']; + $character['range'][$character['rangeid']][] = $width; + } + $character['interval'] = true; + $character['range'][$character['rangeid']]['interval'] = true; + } else { + if ($character['interval']) { + // new range + $character['rangeid'] = $cid; + $character['range'][$character['rangeid']] = []; + $character['range'][$character['rangeid']][] = $width; + } else { + $character['range'][$character['rangeid']][] = $width; + } + $character['interval'] = false; + } + } else { + // new range + $character['rangeid'] = $cid; + $character['range'][$character['rangeid']] = []; + $character['range'][$character['rangeid']][] = $width; + $character['interval'] = false; + } + $character['prevcid'] = $cid; + $character['prevwidth'] = $width; + } + } + $w = $this->writeFontRanges($character['range']); + $this->writer->write($w); + if (!$asSubset) { + $this->fontCache->binaryWrite($font['fontkey'] . '.cw', $w); + } + } + + private function writeFontRanges(&$range) // _putfontranges + { + // optimize ranges + $prevk = -1; + $nextk = -1; + $prevint = false; + foreach ($range as $k => $ws) { + $cws = count($ws); + if (($k == $nextk) and ( !$prevint) and ( (!isset($ws['interval'])) or ( $cws < 4))) { + if (isset($range[$k]['interval'])) { + unset($range[$k]['interval']); + } + $range[$prevk] = array_merge($range[$prevk], $range[$k]); + unset($range[$k]); + } else { + $prevk = $k; + } + $nextk = $k + $cws; + if (isset($ws['interval'])) { + if ($cws > 3) { + $prevint = true; + } else { + $prevint = false; + } + unset($range[$k]['interval']); + --$nextk; + } else { + $prevint = false; + } + } + // output data + $w = ''; + foreach ($range as $k => $ws) { + if (count(array_count_values($ws)) === 1) { + // interval mode is more compact + $w .= ' ' . $k . ' ' . ($k + count($ws) - 1) . ' ' . $ws[0]; + } else { + // range mode + $w .= ' ' . $k . ' [ ' . implode(' ', $ws) . ' ]' . "\n"; + } + } + return '/W [' . $w . ' ]'; + } + + private function writeFontWidths(&$font, $cidoffset = 0) // _putfontwidths + { + ksort($font['cw']); + unset($font['cw'][65535]); + $rangeid = 0; + $range = []; + $prevcid = -2; + $prevwidth = -1; + $interval = false; + // for each character + foreach ($font['cw'] as $cid => $width) { + $cid -= $cidoffset; + if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) { + if ($cid === ($prevcid + 1)) { + // consecutive CID + if ($width === $prevwidth) { + if ($width === $range[$rangeid][0]) { + $range[$rangeid][] = $width; + } else { + array_pop($range[$rangeid]); + // new range + $rangeid = $prevcid; + $range[$rangeid] = []; + $range[$rangeid][] = $prevwidth; + $range[$rangeid][] = $width; + } + $interval = true; + $range[$rangeid]['interval'] = true; + } else { + if ($interval) { + // new range + $rangeid = $cid; + $range[$rangeid] = []; + $range[$rangeid][] = $width; + } else { + $range[$rangeid][] = $width; + } + $interval = false; + } + } else { + // new range + $rangeid = $cid; + $range[$rangeid] = []; + $range[$rangeid][] = $width; + $interval = false; + } + $prevcid = $cid; + $prevwidth = $width; + } + } + $this->writer->write($this->writeFontRanges($range)); + } + + // from class PDF_Chinese CJK EXTENSIONS + public function writeType0(&$font) // _putType0 + { + // Type0 + $this->writer->write('/Subtype /Type0'); + $this->writer->write('/BaseFont /' . $font['name'] . '-' . $font['CMap']); + $this->writer->write('/Encoding /' . $font['CMap']); + $this->writer->write('/DescendantFonts [' . ($this->mpdf->n + 1) . ' 0 R]'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + // CIDFont + $this->writer->object(); + $this->writer->write('<writer->write('/Subtype /CIDFontType0'); + $this->writer->write('/BaseFont /' . $font['name']); + + $cidinfo = '/Registry ' . $this->writer->string('Adobe'); + $cidinfo .= ' /Ordering ' . $this->writer->string($font['registry']['ordering']); + $cidinfo .= ' /Supplement ' . $font['registry']['supplement']; + $this->writer->write('/CIDSystemInfo <<' . $cidinfo . '>>'); + + $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 1) . ' 0 R'); + if (isset($font['MissingWidth'])) { + $this->writer->write('/DW ' . $font['MissingWidth'] . ''); + } + $this->writeFontWidths($font, 31); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + // Font descriptor + $this->writer->object(); + $s = '< $v) { + if ($k !== 'Style') { + $s .= ' /' . $k . ' ' . $v . ''; + } + } + $this->writer->write($s . '>>'); + $this->writer->write('endobj'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/FormWriter.php b/src/vendor/mpdf/mpdf/src/Writer/FormWriter.php new file mode 100644 index 000000000..88c6f356c --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/FormWriter.php @@ -0,0 +1,62 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeFormObjects() // _putformobjects + { + foreach ($this->mpdf->formobjects as $file => $info) { + + $this->writer->object(); + + $this->mpdf->formobjects[$file]['n'] = $this->mpdf->n; + + $this->writer->write('<writer->write('/Subtype /Form'); + $this->writer->write('/Group ' . ($this->mpdf->n + 1) . ' 0 R'); + $this->writer->write('/BBox [' . $info['x'] . ' ' . $info['y'] . ' ' . ($info['w'] + $info['x']) . ' ' . ($info['h'] + $info['y']) . ']'); + + if ($this->mpdf->compress) { + $this->writer->write('/Filter /FlateDecode'); + } + + $data = $this->mpdf->compress ? gzcompress($info['data']) : $info['data']; + $this->writer->write('/Length ' . strlen($data) . '>>'); + $this->writer->stream($data); + + unset($this->mpdf->formobjects[$file]['data']); + + $this->writer->write('endobj'); + + // Required for SVG transparency (opacity) to work + $this->writer->object(); + $this->writer->write('<writer->write('/S /Transparency'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/ImageWriter.php b/src/vendor/mpdf/mpdf/src/Writer/ImageWriter.php new file mode 100644 index 000000000..b4d3ac857 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/ImageWriter.php @@ -0,0 +1,119 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeImages() + { + $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : ''; + + foreach ($this->mpdf->images as $file => $info) { + + $this->writer->object(); + + $this->mpdf->images[$file]['n'] = $this->mpdf->n; + + $this->writer->write('<writer->write('/Subtype /Image'); + $this->writer->write('/Width ' . $info['w']); + $this->writer->write('/Height ' . $info['h']); + + if (isset($info['interpolation']) && $info['interpolation']) { + $this->writer->write('/Interpolate true'); // mPDF 6 - image interpolation shall be performed by a conforming reader + } + + if (isset($info['masked'])) { + $this->writer->write('/SMask ' . ($this->mpdf->n - 1) . ' 0 R'); + } + + // set color space + $icc = false; + if (isset($info['icc']) && ( $info['icc'] !== false)) { + // ICC Colour Space + $icc = true; + $this->writer->write('/ColorSpace [/ICCBased ' . ($this->mpdf->n + 1) . ' 0 R]'); + } elseif ($info['cs'] === 'Indexed') { + if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) { + throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').'); + } + $this->writer->write('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->mpdf->n + 1) . ' 0 R]'); + } else { + $this->writer->write('/ColorSpace /' . $info['cs']); + if ($info['cs'] === 'DeviceCMYK') { + if ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace !== 3) { + throw new \Mpdf\MpdfException('PDFA1-b does not permit Images using mixed colour space (' . $file . ').'); + } + if ($info['type'] === 'jpg') { + $this->writer->write('/Decode [1 0 1 0 1 0 1 0]'); + } + } elseif (($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) && $info['cs'] === 'DeviceRGB') { + throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').'); + } + } + + $this->writer->write('/BitsPerComponent ' . $info['bpc']); + + if (isset($info['f']) && $info['f']) { + $this->writer->write('/Filter /' . $info['f']); + } + + if (isset($info['parms'])) { + $this->writer->write($info['parms']); + } + + if (isset($info['trns']) && is_array($info['trns'])) { + $trns = ''; + $maskCount = count($info['trns']); + for ($i = 0; $i < $maskCount; $i++) { + $trns .= $info['trns'][$i] . ' ' . $info['trns'][$i] . ' '; + } + $this->writer->write('/Mask [' . $trns . ']'); + } + + $this->writer->write('/Length ' . strlen($info['data']) . '>>'); + $this->writer->stream($info['data']); + + unset($this->mpdf->images[$file]['data']); + + $this->writer->write('endobj'); + + if ($icc) { // ICC colour profile + $this->writer->object(); + $icc = $this->mpdf->compress ? gzcompress($info['icc']) : $info['icc']; + $this->writer->write('<>'); + $this->writer->stream($icc); + $this->writer->write('endobj'); + } elseif ($info['cs'] === 'Indexed') { // Palette + $this->writer->object(); + $pal = $this->mpdf->compress ? gzcompress($info['pal']) : $info['pal']; + $this->writer->write('<<' . $filter . '/Length ' . strlen($pal) . '>>'); + $this->writer->stream($pal); + $this->writer->write('endobj'); + } + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/JavaScriptWriter.php b/src/vendor/mpdf/mpdf/src/Writer/JavaScriptWriter.php new file mode 100644 index 000000000..f3bb290ab --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/JavaScriptWriter.php @@ -0,0 +1,46 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeJavascript() // _putjavascript + { + $this->writer->object(); + $this->mpdf->n_js = $this->mpdf->n; + $this->writer->write('<<'); + $this->writer->write('/Names [(EmbeddedJS) ' . (1 + $this->mpdf->n) . ' 0 R ]'); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $this->writer->object(); + $this->writer->write('<<'); + $this->writer->write('/S /JavaScript'); + $this->writer->write('/JS ' . $this->writer->string($this->mpdf->js)); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php b/src/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php new file mode 100644 index 000000000..0cadadaf1 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php @@ -0,0 +1,833 @@ +mpdf = $mpdf; + $this->writer = $writer; + $this->form = $form; + $this->protection = $protection; + $this->logger = $logger; + } + + public function writeMetadata() // _putmetadata + { + $this->writer->object(); + $this->mpdf->MetadataRoot = $this->mpdf->n; + + $z = date('O'); // +0200 + $offset = substr($z, 0, 3) . ':' . substr($z, 3, 2); + + $CreationDate = date('Y-m-d\TH:i:s') . $offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z + + $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff)); + + $m = '' . "\n"; // begin = FEFF BOM + $m .= ' ' . "\n"; + $m .= ' ' . "\n"; + $m .= ' ' . "\n"; + $m .= ' ' . $this->getProducerString() . '' . "\n"; + if (!empty($this->mpdf->keywords)) { + $m .= ' ' . $this->mpdf->keywords . '' . "\n"; + } + $m .= ' ' . "\n"; + + $m .= ' ' . "\n"; + $m .= ' ' . $CreationDate . '' . "\n"; + $m .= ' ' . $CreationDate . '' . "\n"; + $m .= ' ' . $CreationDate . '' . "\n"; + if (!empty($this->mpdf->creator)) { + $m .= ' ' . $this->mpdf->creator . '' . "\n"; + } + $m .= ' ' . "\n"; + + // DC elements + $m .= ' ' . "\n"; + $m .= ' application/pdf' . "\n"; + if (!empty($this->mpdf->title)) { + $m .= ' + + ' . $this->mpdf->title . ' + + ' . "\n"; + } + if (!empty($this->mpdf->keywords)) { + $m .= ' + + ' . $this->mpdf->keywords . ' + + ' . "\n"; + } + if (!empty($this->mpdf->subject)) { + $m .= ' + + ' . $this->mpdf->subject . ' + + ' . "\n"; + } + if (!empty($this->mpdf->author)) { + $m .= ' + + ' . $this->mpdf->author . ' + + ' . "\n"; + } + $m .= ' ' . "\n"; + + if (!empty($this->mpdf->additionalXmpRdf)) { + $m .= $this->mpdf->additionalXmpRdf; + } + + // This bit is specific to PDFX-1a + if ($this->mpdf->PDFX) { + $m .= ' ' . "\n"; + } // This bit is specific to PDFA-1b + elseif ($this->mpdf->PDFA) { + + if (strpos($this->mpdf->PDFAversion, '-') === false) { + throw new \Mpdf\MpdfException(sprintf('PDFA version (%s) is not valid. (Use: 1-B, 3-B, etc.)', $this->mpdf->PDFAversion)); + } + + list($part, $conformance) = explode('-', strtoupper($this->mpdf->PDFAversion)); + $m .= ' ' . "\n"; + $m .= ' ' . $part . '' . "\n"; + $m .= ' ' . $conformance . '' . "\n"; + if ($part === '1' && $conformance === 'B') { + $m .= ' 2005' . "\n"; + } + $m .= ' ' . "\n"; + } + + $m .= ' ' . "\n"; + $m .= ' uuid:' . $uuid . '' . "\n"; + $m .= ' ' . "\n"; + $m .= ' ' . "\n"; + $m .= ' ' . "\n"; + $m .= str_repeat(str_repeat(' ', 100) . "\n", 20); // 2-4kB whitespace padding required + $m .= ''; // "r" read only + $this->writer->write('<>'); + $this->writer->stream($m); + $this->writer->write('endobj'); + } + + public function writeInfo() // _putinfo + { + $this->writer->write('/Producer ' . $this->writer->utf16BigEndianTextString($this->getProducerString())); + + if (!empty($this->mpdf->title)) { + $this->writer->write('/Title ' . $this->writer->utf16BigEndianTextString($this->mpdf->title)); + } + + if (!empty($this->mpdf->subject)) { + $this->writer->write('/Subject ' . $this->writer->utf16BigEndianTextString($this->mpdf->subject)); + } + + if (!empty($this->mpdf->author)) { + $this->writer->write('/Author ' . $this->writer->utf16BigEndianTextString($this->mpdf->author)); + } + + if (!empty($this->mpdf->keywords)) { + $this->writer->write('/Keywords ' . $this->writer->utf16BigEndianTextString($this->mpdf->keywords)); + } + + if (!empty($this->mpdf->creator)) { + $this->writer->write('/Creator ' . $this->writer->utf16BigEndianTextString($this->mpdf->creator)); + } + + foreach ($this->mpdf->customProperties as $key => $value) { + $this->writer->write('/' . $key . ' ' . $this->writer->utf16BigEndianTextString($value)); + } + + $now = PdfDate::format(time()); + $this->writer->write('/CreationDate ' . $this->writer->string('D:' . $now)); + $this->writer->write('/ModDate ' . $this->writer->string('D:' . $now)); + if ($this->mpdf->PDFX) { + $this->writer->write('/Trapped/False'); + $this->writer->write('/GTS_PDFXVersion(PDF/X-1a:2003)'); + } + } + + public function writeOutputIntent() // _putoutputintent + { + $this->writer->object(); + $this->mpdf->OutputIntentRoot = $this->mpdf->n; + $this->writer->write('<mpdf->ICCProfile, '.icc')); + + if ($this->mpdf->PDFA) { + $this->writer->write('/S /GTS_PDFA1'); + if ($this->mpdf->ICCProfile) { + $this->writer->write('/Info (' . $ICCProfile . ')'); + $this->writer->write('/OutputConditionIdentifier (Custom)'); + $this->writer->write('/OutputCondition ()'); + } else { + $this->writer->write('/Info (sRGB IEC61966-2.1)'); + $this->writer->write('/OutputConditionIdentifier (sRGB IEC61966-2.1)'); + $this->writer->write('/OutputCondition ()'); + } + $this->writer->write('/DestOutputProfile ' . ($this->mpdf->n + 1) . ' 0 R'); + } elseif ($this->mpdf->PDFX) { // always a CMYK profile + $this->writer->write('/S /GTS_PDFX'); + if ($this->mpdf->ICCProfile) { + $this->writer->write('/Info (' . $ICCProfile . ')'); + $this->writer->write('/OutputConditionIdentifier (Custom)'); + $this->writer->write('/OutputCondition ()'); + $this->writer->write('/DestOutputProfile ' . ($this->mpdf->n + 1) . ' 0 R'); + } else { + $this->writer->write('/Info (CGATS TR 001)'); + $this->writer->write('/OutputConditionIdentifier (CGATS TR 001)'); + $this->writer->write('/OutputCondition (CGATS TR 001 (SWOP))'); + $this->writer->write('/RegistryName (http://www.color.org)'); + } + } + $this->writer->write('>>'); + $this->writer->write('endobj'); + + if ($this->mpdf->PDFX && !$this->mpdf->ICCProfile) { + return; + } + + $this->writer->object(); + + if ($this->mpdf->ICCProfile) { + if (!file_exists($this->mpdf->ICCProfile)) { + throw new \Mpdf\MpdfException(sprintf('Unable to find ICC profile "%s"', $this->mpdf->ICCProfile)); + } + $s = file_get_contents($this->mpdf->ICCProfile); + } else { + $s = file_get_contents(__DIR__ . '/../../data/iccprofiles/sRGB_IEC61966-2-1.icc'); + } + + if ($this->mpdf->compress) { + $s = gzcompress($s); + } + + $this->writer->write('<<'); + + if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) { + $this->writer->write('/N 4'); + } else { + $this->writer->write('/N 3'); + } + + if ($this->mpdf->compress) { + $this->writer->write('/Filter /FlateDecode '); + } + + $this->writer->write('/Length ' . strlen($s) . '>>'); + $this->writer->stream($s); + $this->writer->write('endobj'); + } + + public function writeAssociatedFiles() // _putAssociatedFiles + { + if (!function_exists('gzcompress')) { + throw new \Mpdf\MpdfException('ext-zlib is required for compression of associated files'); + } + + // for each file, we create the spec object + the stream object + foreach ($this->mpdf->associatedFiles as $k => $file) { + // spec + $this->writer->object(); + $this->mpdf->associatedFiles[$k]['_root'] = $this->mpdf->n; // we store the root ref of object for future reference (e.g. /EmbeddedFiles catalog) + $this->writer->write('<writer->string($file['name'])); + if ($file['description']) { + $this->writer->write('/Desc ' . $this->writer->string($file['description'])); + } + $this->writer->write('/Type /Filespec'); + $this->writer->write('/EF <<'); + $this->writer->write('/F ' . ($this->mpdf->n + 1) . ' 0 R'); + $this->writer->write('/UF ' . ($this->mpdf->n + 1) . ' 0 R'); + $this->writer->write('>>'); + if ($file['AFRelationship']) { + $this->writer->write('/AFRelationship /' . $file['AFRelationship']); + } + $this->writer->write('/UF ' . $this->writer->string($file['name'])); + $this->writer->write('>>'); + $this->writer->write('endobj'); + + $fileContent = null; + if (isset($file['path'])) { + $fileContent = @file_get_contents($file['path']); + } elseif (isset($file['content'])) { + $fileContent = $file['content']; + } + + if (!$fileContent) { + throw new \Mpdf\MpdfException(sprintf('Cannot access associated file - %s', $file['path'])); + } + + $filestream = gzcompress($fileContent); + $this->writer->object(); + $this->writer->write('<writer->write('/Subtype /' . $this->writer->escapeSlashes($file['mime'])); + } + $this->writer->write('/Length ' . strlen($filestream)); + $this->writer->write('/Filter /FlateDecode'); + if (isset($file['path'])) { + $this->writer->write('/Params <writer->string('D:' . PdfDate::format(filemtime($file['path']))).' >>'); + } else { + $this->writer->write('/Params <writer->string('D:' . PdfDate::format(time())).' >>'); + } + + $this->writer->write('>>'); + $this->writer->stream($filestream); + $this->writer->write('endobj'); + } + + // AF array + $this->writer->object(); + $refs = []; + foreach ($this->mpdf->associatedFiles as $file) { + $refs[] = '' . $file['_root'] . ' 0 R'; + } + $this->writer->write('[' . implode(' ', $refs) . ']'); + $this->writer->write('endobj'); + + $this->mpdf->associatedFilesRoot = $this->mpdf->n; + } + + public function writeCatalog() //_putcatalog + { + $this->writer->write('/Type /Catalog'); + $this->writer->write('/Pages 1 0 R'); + + if (is_string($this->mpdf->currentLang)) { + $this->writer->write(sprintf('/Lang (%s)', $this->mpdf->currentLang)); + } elseif (is_string($this->mpdf->default_lang)) { + $this->writer->write(sprintf('/Lang (%s)', $this->mpdf->default_lang)); + } + + if ($this->mpdf->ZoomMode === 'fullpage') { + $this->writer->write('/OpenAction [3 0 R /Fit]'); + } elseif ($this->mpdf->ZoomMode === 'fullwidth') { + $this->writer->write('/OpenAction [3 0 R /FitH null]'); + } elseif ($this->mpdf->ZoomMode === 'real') { + $this->writer->write('/OpenAction [3 0 R /XYZ null null 1]'); + } elseif (!is_string($this->mpdf->ZoomMode)) { + $this->writer->write('/OpenAction [3 0 R /XYZ null null ' . ($this->mpdf->ZoomMode / 100) . ']'); + } elseif ($this->mpdf->ZoomMode === 'none') { + // do not write any zoom mode / OpenAction + } else { + $this->writer->write('/OpenAction [3 0 R /XYZ null null null]'); + } + + if ($this->mpdf->LayoutMode === 'single') { + $this->writer->write('/PageLayout /SinglePage'); + } elseif ($this->mpdf->LayoutMode === 'continuous') { + $this->writer->write('/PageLayout /OneColumn'); + } elseif ($this->mpdf->LayoutMode === 'twoleft') { + $this->writer->write('/PageLayout /TwoColumnLeft'); + } elseif ($this->mpdf->LayoutMode === 'tworight') { + $this->writer->write('/PageLayout /TwoColumnRight'); + } elseif ($this->mpdf->LayoutMode === 'two') { + if ($this->mpdf->mirrorMargins) { + $this->writer->write('/PageLayout /TwoColumnRight'); + } else { + $this->writer->write('/PageLayout /TwoColumnLeft'); + } + } + + // Bookmarks + if (count($this->mpdf->BMoutlines) > 0) { + $this->writer->write('/Outlines ' . $this->mpdf->OutlineRoot . ' 0 R'); + $this->writer->write('/PageMode /UseOutlines'); + } + + // Fullscreen + if (is_int(strpos($this->mpdf->DisplayPreferences, 'FullScreen'))) { + $this->writer->write('/PageMode /FullScreen'); + } + + // Metadata + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { + $this->writer->write('/Metadata ' . $this->mpdf->MetadataRoot . ' 0 R'); + } + + // OutputIntents + if ($this->mpdf->PDFA || $this->mpdf->PDFX || $this->mpdf->ICCProfile) { + $this->writer->write('/OutputIntents [' . $this->mpdf->OutputIntentRoot . ' 0 R]'); + } + + // Associated files + if ($this->mpdf->associatedFilesRoot) { + $this->writer->write('/AF '. $this->mpdf->associatedFilesRoot .' 0 R'); + + $names = []; + foreach ($this->mpdf->associatedFiles as $file) { + $names[] = $this->writer->string($file['name']) . ' ' . $file['_root'] . ' 0 R'; + } + $this->writer->write('/Names << /EmbeddedFiles << /Names [' . implode(' ', $names) . '] >> >>'); + } + + // Forms + if (count($this->form->forms) > 0) { + $this->form->_putFormsCatalog(); + } + + if ($this->mpdf->js !== null) { + $this->writer->write('/Names << /JavaScript ' . $this->mpdf->n_js . ' 0 R >> '); + } + + if ($this->mpdf->DisplayPreferences || $this->mpdf->directionality === 'rtl' || $this->mpdf->mirrorMargins) { + + $this->writer->write('/ViewerPreferences<<'); + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideMenubar'))) { + $this->writer->write('/HideMenubar true'); + } + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideToolbar'))) { + $this->writer->write('/HideToolbar true'); + } + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideWindowUI'))) { + $this->writer->write('/HideWindowUI true'); + } + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'DisplayDocTitle'))) { + $this->writer->write('/DisplayDocTitle true'); + } + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'CenterWindow'))) { + $this->writer->write('/CenterWindow true'); + } + + if (is_int(strpos($this->mpdf->DisplayPreferences, 'FitWindow'))) { + $this->writer->write('/FitWindow true'); + } + + // PrintScaling is PDF 1.6 spec. + if (!$this->mpdf->PDFA && !$this->mpdf->PDFX && is_int(strpos($this->mpdf->DisplayPreferences, 'NoPrintScaling'))) { + $this->writer->write('/PrintScaling /None'); + } + + if ($this->mpdf->directionality === 'rtl') { + $this->writer->write('/Direction /R2L'); + } + + // Duplex is PDF 1.7 spec. + if ($this->mpdf->mirrorMargins && !$this->mpdf->PDFA && !$this->mpdf->PDFX) { + // if ($this->mpdf->DefOrientation=='P') $this->writer->write('/Duplex /DuplexFlipShortEdge'); + $this->writer->write('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+ + } + + $this->writer->write('>>'); + } + + if ($this->mpdf->open_layer_pane && ($this->mpdf->hasOC || count($this->mpdf->layers))) { + $this->writer->write('/PageMode /UseOC'); + } + + if ($this->mpdf->hasOC || count($this->mpdf->layers)) { + + $p = $v = $h = $l = $loff = $lall = $as = ''; + + if ($this->mpdf->hasOC) { + + if (($this->mpdf->hasOC & 1) === 1) { + $p = $this->mpdf->n_ocg_print . ' 0 R'; + } + + if (($this->mpdf->hasOC & 2) === 2) { + $v = $this->mpdf->n_ocg_view . ' 0 R'; + } + + if (($this->mpdf->hasOC & 4) === 4) { + $h = $this->mpdf->n_ocg_hidden . ' 0 R'; + } + + $as = "<> <>"; + } + + if (count($this->mpdf->layers)) { + foreach ($this->mpdf->layers as $k => $layer) { + if (isset($this->mpdf->layerDetails[$k]) && strtolower($this->mpdf->layerDetails[$k]['state']) === 'hidden') { + $loff .= $layer['n'] . ' 0 R '; + } else { + $l .= $layer['n'] . ' 0 R '; + } + $lall .= $layer['n'] . ' 0 R '; + } + } + + $this->writer->write("/OCProperties <writer->write("/Order [$v $p $h $lall] "); + + if ($as) { + $this->writer->write("/AS [$as] "); + } + + $this->writer->write('>>>>'); + } + } + + /** + * @since 5.7.2 + */ + public function writeAnnotations() // _putannots + { + $nb = $this->mpdf->page; + + for ($n = 1; $n <= $nb; $n++) { + + if (isset($this->mpdf->PageLinks[$n]) || isset($this->mpdf->PageAnnots[$n]) || count($this->form->forms) > 0) { + + $wPt = $this->mpdf->pageDim[$n]['w'] * Mpdf::SCALE; + $hPt = $this->mpdf->pageDim[$n]['h'] * Mpdf::SCALE; + + // Links + if (isset($this->mpdf->PageLinks[$n])) { + + foreach ($this->mpdf->PageLinks[$n] as $key => $pl) { + + $this->writer->object(); + $annot = ''; + + $rect = sprintf('%.3F %.3F %.3F %.3F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]); + + $annot .= '<writer->utf16BigEndianTextString($pl[4]); + $annot .= ' /NM ' . $this->writer->string(sprintf('%04u-%04u', $n, $key)); + $annot .= ' /M ' . $this->writer->string('D:' . date('YmdHis')); + + $annot .= ' /Border [0 0 0]'; + + // Use this (instead of /Border) to specify border around link + + // $annot .= ' /BS <mpdf->PDFA || $this->mpdf->PDFX) { + $annot .= ' /F 28'; + } + + if (strpos($pl[4], '@') === 0) { + + $p = substr($pl[4], 1); + // $h=isset($this->mpdf->OrientationChanges[$p]) ? $wPt : $hPt; + $htarg = $this->mpdf->pageDim[$p]['h'] * Mpdf::SCALE; + $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $p, $htarg); + + } elseif (is_string($pl[4])) { + + $annot .= ' /A <writer->string($pl[4]) . '>> >>'; + + } else { + + $l = $this->mpdf->links[$pl[4]]; + // may not be set if #link points to non-existent target + if (isset($this->mpdf->pageDim[$l[0]]['h'])) { + $htarg = $this->mpdf->pageDim[$l[0]]['h'] * Mpdf::SCALE; + } else { + $htarg = $this->mpdf->h * Mpdf::SCALE; + } // doesn't really matter + + $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $l[0], $htarg - $l[1] * Mpdf::SCALE); + } + + $this->writer->write($annot); + $this->writer->write('endobj'); + + } + } + + /* -- ANNOTATIONS -- */ + if (isset($this->mpdf->PageAnnots[$n])) { + + foreach ($this->mpdf->PageAnnots[$n] as $key => $pl) { + + $fileAttachment = (bool) $pl['opt']['file']; + + if ($fileAttachment && !$this->mpdf->allowAnnotationFiles) { + $this->logger->warning('Embedded files for annotations have to be allowed explicitly with "allowAnnotationFiles" config key'); + $fileAttachment = false; + } + + $this->writer->object(); + + $annot = ''; + $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER); + $x = $pl['x']; + + if ($this->mpdf->annotMargin != 0 || $x == 0 || $x < 0) { // Odd page, intentional non-strict comparison + $x = ($wPt / Mpdf::SCALE) - $this->mpdf->annotMargin; + } + + $w = $h = 0; + $a = $x * Mpdf::SCALE; + $b = $hPt - ($pl['y'] * Mpdf::SCALE); + + $annot .= '<mpdf->n + 1) . ' 0 R>>'; + $annot .= '>>'; + + } else { + $annot .= '/Subtype /Text'; + $w = 20; + $h = 20; // mPDF 6 + } + + $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b - $h, $a + $w, $b); + $annot .= ' /Rect [' . $rect . ']'; + + // contents = description of file in free text + $annot .= ' /Contents ' . $this->writer->utf16BigEndianTextString($pl['txt']); + + $annot .= ' /NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 2000 + $key)); + $annot .= ' /M ' . $this->writer->string('D:' . date('YmdHis')); + $annot .= ' /CreationDate ' . $this->writer->string('D:' . date('YmdHis')); + $annot .= ' /Border [0 0 0]'; + + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { + $annot .= ' /F 28'; + $annot .= ' /CA 1'; + } elseif ($pl['opt']['ca'] > 0) { + $annot .= ' /CA ' . $pl['opt']['ca']; + } + + $annotcolor = ' /C ['; + if (isset($pl['opt']['c']) && $pl['opt']['c']) { + $col = $pl['opt']['c']; + if ($col[0] == 3 || $col[0] == 5) { + $annotcolor .= sprintf('%.3F %.3F %.3F', ord($col[1]) / 255, ord($col[2]) / 255, ord($col[3]) / 255); + } elseif ($col[0] == 1) { + $annotcolor .= sprintf('%.3F', ord($col[1]) / 255); + } elseif ($col[0] == 4 || $col[0] == 6) { + $annotcolor .= sprintf('%.3F %.3F %.3F %.3F', ord($col[1]) / 100, ord($col[2]) / 100, ord($col[3]) / 100, ord($col[4]) / 100); + } else { + $annotcolor .= '1 1 0'; + } + } else { + $annotcolor .= '1 1 0'; + } + $annotcolor .= ']'; + $annot .= $annotcolor; + + // Usually Author + // Use as Title for fileattachment + if (isset($pl['opt']['t']) && is_string($pl['opt']['t'])) { + $annot .= ' /T ' . $this->writer->utf16BigEndianTextString($pl['opt']['t']); + } + + if ($fileAttachment) { + $iconsapp = ['Paperclip', 'Graph', 'PushPin', 'Tag']; + } else { + $iconsapp = ['Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph']; + } + + if (isset($pl['opt']['icon']) && in_array($pl['opt']['icon'], $iconsapp)) { + $annot .= ' /Name /' . $pl['opt']['icon']; + } elseif ($fileAttachment) { + $annot .= ' /Name /PushPin'; + } else { + $annot .= ' /Name /Note'; + } + + if (!$fileAttachment) { + // Subj is PDF 1.5 spec. + if (!$this->mpdf->PDFA && !$this->mpdf->PDFX && isset($pl['opt']['subj'])) { + $annot .= ' /Subj ' . $this->writer->utf16BigEndianTextString($pl['opt']['subj']); + } + if (!empty($pl['opt']['popup'])) { + $annot .= ' /Open true'; + $annot .= ' /Popup ' . ($this->mpdf->n + 1) . ' 0 R'; + } else { + $annot .= ' /Open false'; + } + } + + $annot .= ' /P ' . $pl['pageobj'] . ' 0 R'; + $annot .= '>>'; + $this->writer->write($annot); + $this->writer->write('endobj'); + + if ($fileAttachment) { + + $file = @file_get_contents($pl['opt']['file']); + if (!$file) { + throw new \Mpdf\MpdfException('mPDF Error: Cannot access file attachment - ' . $pl['opt']['file']); + } + + $filestream = gzcompress($file); + $this->writer->object(); + $this->writer->write('<writer->write('/Length ' . strlen($filestream)); + $this->writer->write('/Filter /FlateDecode'); + $this->writer->write('>>'); + $this->writer->stream($filestream); + $this->writer->write('endobj'); + + } elseif (!empty($pl['opt']['popup'])) { + $this->writer->object(); + $annot = ''; + if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) { + $x = $pl['opt']['popup'][0] * Mpdf::SCALE; + } else { + $x = $pl['x'] * Mpdf::SCALE; + } + if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) { + $y = $hPt - ($pl['opt']['popup'][1] * Mpdf::SCALE); + } else { + $y = $hPt - ($pl['y'] * Mpdf::SCALE); + } + if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) { + $w = $pl['opt']['popup'][2] * Mpdf::SCALE; + } else { + $w = 180; + } + if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) { + $h = $pl['opt']['popup'][3] * Mpdf::SCALE; + } else { + $h = 120; + } + $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y - $h, $x + $w, $y); + $annot .= '<writer->string('D:' . date('YmdHis')); + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { + $annot .= ' /F 28'; + } + $annot .= ' /Parent ' . ($this->mpdf->n - 1) . ' 0 R'; + $annot .= '>>'; + $this->writer->write($annot); + $this->writer->write('endobj'); + } + } + } + + // Active Forms + if (count($this->form->forms) > 0) { + $this->form->_putFormItems($n, $hPt); + } + } + } + + // Active Forms - Radio Button Group entries + // Output Radio Button Group form entries (radio_on_obj_id already determined) + if (count($this->form->form_radio_groups)) { + $this->form->_putRadioItems($n); + } + } + + public function writeEncryption() // _putencryption + { + $this->writer->write('/Filter /Standard'); + if ($this->protection->getUseRC128Encryption()) { + $this->writer->write('/V 2'); + $this->writer->write('/R 3'); + $this->writer->write('/Length 128'); + } else { + $this->writer->write('/V 1'); + $this->writer->write('/R 2'); + } + $this->writer->write('/O (' . $this->writer->escape($this->protection->getOValue()) . ')'); + $this->writer->write('/U (' . $this->writer->escape($this->protection->getUValue()) . ')'); + $this->writer->write('/P ' . $this->protection->getPValue()); + } + + public function writeTrailer() // _puttrailer + { + $this->writer->write('/Size ' . ($this->mpdf->n + 1)); + $this->writer->write('/Root ' . $this->mpdf->n . ' 0 R'); + $this->writer->write('/Info ' . $this->mpdf->InfoRoot . ' 0 R'); + + if ($this->mpdf->encrypted) { + $this->writer->write('/Encrypt ' . $this->mpdf->enc_obj_id . ' 0 R'); + $this->writer->write('/ID [<' . $this->protection->getUniqid() . '> <' . $this->protection->getUniqid() . '>]'); + } else { + $uniqid = md5(time() . $this->mpdf->buffer); + $this->writer->write('/ID [<' . $uniqid . '> <' . $uniqid . '>]'); + } + } + + private function getVersionString() + { + $return = Mpdf::VERSION; + $headFile = __DIR__ . '/../../.git/HEAD'; + if (file_exists($headFile)) { + $ref = file($headFile); + $path = explode('/', $ref[0], 3); + $branch = isset($path[2]) ? trim($path[2]) : ''; + $revFile = __DIR__ . '/../../.git/refs/heads/' . $branch; + if ($branch && file_exists($revFile)) { + $rev = file($revFile); + $rev = substr($rev[0], 0, 7); + $return .= ' (' . $rev . ')'; + } + } + + return $return; + } + + private function getProducerString() + { + return 'mPDF' . ($this->mpdf->exposeVersion ? (' ' . $this->getVersionString()) : ''); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/ObjectWriter.php b/src/vendor/mpdf/mpdf/src/Writer/ObjectWriter.php new file mode 100644 index 000000000..2e0ad7d01 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/ObjectWriter.php @@ -0,0 +1,64 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeImportedObjects() + { + if (is_array($this->mpdf->parsers) && count($this->mpdf->parsers) > 0) { + + foreach ($this->mpdf->parsers as $filename => $p) { + + $this->mpdf->current_parser = $this->mpdf->parsers[$filename]; + + if (is_array($this->mpdf->_obj_stack[$filename])) { + + while ($n = key($this->mpdf->_obj_stack[$filename])) { + + $nObj = $this->mpdf->current_parser->resolveObject($this->mpdf->_obj_stack[$filename][$n][1]); + $this->writer->object($this->mpdf->_obj_stack[$filename][$n][0]); + + if ($nObj[0] == pdf_parser::TYPE_STREAM) { + $this->mpdf->pdf_write_value($nObj); + } else { + $this->mpdf->pdf_write_value($nObj[1]); + } + + $this->writer->write('endobj'); + + $this->mpdf->_obj_stack[$filename][$n] = null; // free memory + + unset($this->mpdf->_obj_stack[$filename][$n]); + + reset($this->mpdf->_obj_stack[$filename]); + } + } + } + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/OptionalContentWriter.php b/src/vendor/mpdf/mpdf/src/Writer/OptionalContentWriter.php new file mode 100644 index 000000000..499a77fd7 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/OptionalContentWriter.php @@ -0,0 +1,71 @@ +mpdf = $mpdf; + $this->writer = $writer; + } + + public function writeOptionalContentGroups() // _putocg Optional Content Groups + { + if ($this->mpdf->hasOC) { + + $this->writer->object(); + $this->mpdf->n_ocg_print = $this->mpdf->n; + $this->writer->write('<writer->string('Print only')); + $this->writer->write('/Usage <> /View <>>>>>'); + $this->writer->write('endobj'); + + $this->writer->object(); + $this->mpdf->n_ocg_view = $this->mpdf->n; + $this->writer->write('<writer->string('Screen only')); + $this->writer->write('/Usage <> /View <>>>>>'); + $this->writer->write('endobj'); + + $this->writer->object(); + $this->mpdf->n_ocg_hidden = $this->mpdf->n; + $this->writer->write('<writer->string('Hidden')); + $this->writer->write('/Usage <> /View <>>>>>'); + $this->writer->write('endobj'); + } + + if (count($this->mpdf->layers)) { + + ksort($this->mpdf->layers); + foreach ($this->mpdf->layers as $id => $layer) { + $this->writer->object(); + $this->mpdf->layers[$id]['n'] = $this->mpdf->n; + + if (isset($this->mpdf->layerDetails[$id]['name']) && $this->mpdf->layerDetails[$id]['name']) { + $name = $this->mpdf->layerDetails[$id]['name']; + } else { + $name = $layer['name']; + } + + $this->writer->write('<writer->utf16BigEndianTextString($name) . '>>'); + $this->writer->write('endobj'); + } + } + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/PageWriter.php b/src/vendor/mpdf/mpdf/src/Writer/PageWriter.php new file mode 100644 index 000000000..7e4e21d47 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/PageWriter.php @@ -0,0 +1,285 @@ +mpdf = $mpdf; + $this->form = $form; + $this->writer = $writer; + $this->metadataWriter = $metadataWriter; + } + + public function writePages() // _putpages + { + $nb = $this->mpdf->page; + $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : ''; + + if ($this->mpdf->DefOrientation === 'P') { + $defwPt = $this->mpdf->fwPt; + $defhPt = $this->mpdf->fhPt; + } else { + $defwPt = $this->mpdf->fhPt; + $defhPt = $this->mpdf->fwPt; + } + + $annotid = (3 + 2 * $nb); + + // Active Forms + $totaladdnum = 0; + for ($n = 1; $n <= $nb; $n++) { + if (isset($this->mpdf->PageLinks[$n])) { + $totaladdnum += count($this->mpdf->PageLinks[$n]); + } + + /* -- ANNOTATIONS -- */ + if (isset($this->mpdf->PageAnnots[$n])) { + foreach ($this->mpdf->PageAnnots[$n] as $k => $pl) { + if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { + $totaladdnum += 2; + } else { + $totaladdnum++; + } + } + } + /* -- END ANNOTATIONS -- */ + + /* -- FORMS -- */ + if (count($this->form->forms) > 0) { + $this->form->countPageForms($n, $totaladdnum); + } + /* -- END FORMS -- */ + } + + /* -- FORMS -- */ + // Make a note in the radio button group of the obj_id it will have + $ctr = 0; + if (count($this->form->form_radio_groups)) { + foreach ($this->form->form_radio_groups as $name => $frg) { + $this->form->form_radio_groups[$name]['obj_id'] = $annotid + $totaladdnum + $ctr; + $ctr++; + } + } + /* -- END FORMS -- */ + + // Select unused fonts (usually default font) + $unused = []; + foreach ($this->mpdf->fonts as $fk => $font) { + if (isset($font['type']) && $font['type'] === 'TTF' && !$font['used']) { + $unused[] = $fk; + } + } + + for ($n = 1; $n <= $nb; $n++) { + + $thispage = $this->mpdf->pages[$n]; + + if (isset($this->mpdf->OrientationChanges[$n])) { + $hPt = $this->mpdf->pageDim[$n]['w'] * Mpdf::SCALE; + $wPt = $this->mpdf->pageDim[$n]['h'] * Mpdf::SCALE; + $owidthPt_LR = $this->mpdf->pageDim[$n]['outer_width_TB'] * Mpdf::SCALE; + $owidthPt_TB = $this->mpdf->pageDim[$n]['outer_width_LR'] * Mpdf::SCALE; + } else { + $wPt = $this->mpdf->pageDim[$n]['w'] * Mpdf::SCALE; + $hPt = $this->mpdf->pageDim[$n]['h'] * Mpdf::SCALE; + $owidthPt_LR = $this->mpdf->pageDim[$n]['outer_width_LR'] * Mpdf::SCALE; + $owidthPt_TB = $this->mpdf->pageDim[$n]['outer_width_TB'] * Mpdf::SCALE; + } + + // Remove references to unused fonts (usually default font) + foreach ($unused as $fk) { + if ($this->mpdf->fonts[$fk]['sip'] || $this->mpdf->fonts[$fk]['smp']) { + foreach ($this->mpdf->fonts[$fk]['subsetfontids'] as $k => $fid) { + $thispage = preg_replace('/\s\/F' . $fid . ' \d[\d.]* Tf\s/is', ' ', $thispage); + } + } else { + $thispage = preg_replace('/\s\/F' . $this->mpdf->fonts[$fk]['i'] . ' \d[\d.]* Tf\s/is', ' ', $thispage); + } + } + + // Clean up repeated /GS1 gs statements + // For some reason using + for repetition instead of {2,20} crashes PHP Script Interpreter ??? + $thispage = preg_replace('/(\/GS1 gs\n){2,20}/', "/GS1 gs\n", $thispage); + + $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS' . $this->mpdf->uniqstr . '\s*)/', ' ', $thispage); + $thispage = preg_replace('/(\s*___HEADER___MARKER' . $this->mpdf->uniqstr . '\s*)/', ' ', $thispage); + $thispage = preg_replace('/(\s*___PAGE___START' . $this->mpdf->uniqstr . '\s*)/', ' ', $thispage); + $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS' . $this->mpdf->uniqstr . '\s*)/', ' ', $thispage); + + // mPDF 5.7.3 TRANSFORMS + while (preg_match('/(\% BTR(.*?)\% ETR)/is', $thispage, $m)) { + $thispage = preg_replace('/(\% BTR.*?\% ETR)/is', '', $thispage, 1) . "\n" . $m[2]; + } + + // Page + $this->writer->object(); + $this->writer->write('<writer->write('/Parent 1 0 R'); + + if (isset($this->mpdf->OrientationChanges[$n])) { + + $this->writer->write(sprintf('/MediaBox [0 0 %.3F %.3F]', $hPt, $wPt)); + + // If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox + $bleedMargin = $this->mpdf->pageDim[$n]['bleedMargin'] * Mpdf::SCALE; + + if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) { + $x0 = $owidthPt_TB - $bleedMargin; + $y0 = $owidthPt_LR - $bleedMargin; + $x1 = $hPt - $owidthPt_TB + $bleedMargin; + $y1 = $wPt - $owidthPt_LR + $bleedMargin; + $this->writer->write(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1)); + } + + $this->writer->write(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, $hPt - $owidthPt_TB, $wPt - $owidthPt_LR)); + + if ($this->mpdf->displayDefaultOrientation) { + if ($this->mpdf->DefOrientation === 'P') { + $this->writer->write('/Rotate 270'); + } else { + $this->writer->write('/Rotate 90'); + } + } + + } else { // elseif($wPt != $defwPt || $hPt != $defhPt) { + + $this->writer->write(sprintf('/MediaBox [0 0 %.3F %.3F]', $wPt, $hPt)); + $bleedMargin = $this->mpdf->pageDim[$n]['bleedMargin'] * Mpdf::SCALE; + + if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) { + $x0 = $owidthPt_LR - $bleedMargin; + $y0 = $owidthPt_TB - $bleedMargin; + $x1 = $wPt - $owidthPt_LR + $bleedMargin; + $y1 = $hPt - $owidthPt_TB + $bleedMargin; + $this->writer->write(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1)); + } + + $this->writer->write(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, $wPt - $owidthPt_LR, $hPt - $owidthPt_TB)); + } + $this->writer->write('/Resources 2 0 R'); + + // Important to keep in RGB colorSpace when using transparency + if (!$this->mpdf->PDFA && !$this->mpdf->PDFX) { + if ($this->mpdf->restrictColorSpace === 3) { + $this->writer->write('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> '); + } elseif ($this->mpdf->restrictColorSpace === 1) { + $this->writer->write('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> '); + } else { + $this->writer->write('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> '); + } + } + + $annotsnum = 0; + $embeddedfiles = []; // mPDF 5.7.2 /EmbeddedFiles + + if (isset($this->mpdf->PageLinks[$n])) { + $annotsnum += count($this->mpdf->PageLinks[$n]); + } + + if (isset($this->mpdf->PageAnnots[$n])) { + foreach ($this->mpdf->PageAnnots[$n] as $k => $pl) { + if (!empty($pl['opt']['file'])) { + $embeddedfiles[$annotsnum + 1] = true; + } // mPDF 5.7.2 /EmbeddedFiles + if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) { + $annotsnum += 2; + } else { + $annotsnum++; + } + $this->mpdf->PageAnnots[$n][$k]['pageobj'] = $this->mpdf->n; + } + } + + // Active Forms + $formsnum = 0; + if (count($this->form->forms) > 0) { + foreach ($this->form->forms as $val) { + if ($val['page'] == $n) { + $formsnum++; + } + } + } + + if ($annotsnum || $formsnum) { + + $s = '/Annots [ '; + + for ($i = 0; $i < $annotsnum; $i++) { + if (!isset($embeddedfiles[$i])) { + $s .= ($annotid + $i) . ' 0 R '; + } // mPDF 5.7.2 /EmbeddedFiles + } + + $annotid += $annotsnum; + + /* -- FORMS -- */ + if (count($this->form->forms) > 0) { + $this->form->addFormIds($n, $s, $annotid); + } + /* -- END FORMS -- */ + + $s .= '] '; + $this->writer->write($s); + } + + $this->writer->write('/Contents ' . ($this->mpdf->n + 1) . ' 0 R>>'); + $this->writer->write('endobj'); + + // Page content + $this->writer->object(); + $p = $this->mpdf->compress ? gzcompress($thispage) : $thispage; + $this->writer->write('<<' . $filter . '/Length ' . strlen($p) . '>>'); + $this->writer->stream($p); + $this->writer->write('endobj'); + } + + $this->metadataWriter->writeAnnotations(); // mPDF 5.7.2 + + // Pages root + $this->mpdf->offsets[1] = strlen($this->mpdf->buffer); + $this->writer->write('1 0 obj'); + $this->writer->write('<writer->write($kids . ']'); + $this->writer->write('/Count ' . $nb); + $this->writer->write(sprintf('/MediaBox [0 0 %.3F %.3F]', $defwPt, $defhPt)); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + +} diff --git a/src/vendor/mpdf/mpdf/src/Writer/ResourceWriter.php b/src/vendor/mpdf/mpdf/src/Writer/ResourceWriter.php new file mode 100644 index 000000000..001d8c8b6 --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/Writer/ResourceWriter.php @@ -0,0 +1,243 @@ +mpdf = $mpdf; + $this->writer = $writer; + $this->colorWriter = $colorWriter; + $this->fontWriter = $fontWriter; + $this->imageWriter = $imageWriter; + $this->formWriter = $formWriter; + $this->optionalContentWriter = $optionalContentWriter; + $this->backgroundWriter = $backgroundWriter; + $this->bookmarkWriter = $bookmarkWriter; + $this->metadataWriter = $metadataWriter; + $this->javaScriptWriter = $javaScriptWriter; + $this->logger = $logger; + } + + public function writeResources() // _putresources + { + if ($this->mpdf->hasOC || count($this->mpdf->layers)) { + $this->optionalContentWriter->writeOptionalContentGroups(); + } + + $this->mpdf->_putextgstates(); + $this->colorWriter->writeSpotColors(); + + // @log Compiling Fonts + + $this->fontWriter->writeFonts(); + + // @log Compiling Images + + $this->imageWriter->writeImages(); + + $this->formWriter->writeFormObjects(); + + $this->mpdf->writeImportedPagesAndResolvedObjects(); + + $this->backgroundWriter->writeShaders(); + $this->backgroundWriter->writePatterns(); + + // Resource dictionary + $this->mpdf->offsets[2] = strlen($this->mpdf->buffer); + $this->writer->write('2 0 obj'); + $this->writer->write('<writer->write('/Font <<'); + foreach ($this->mpdf->fonts as $font) { + if (isset($font['type']) && $font['type'] === 'TTF' && !$font['used']) { + continue; + } + if (isset($font['type']) && $font['type'] === 'TTF' && ($font['sip'] || $font['smp'])) { + foreach ($font['n'] as $k => $fid) { + $this->writer->write('/F' . $font['subsetfontids'][$k] . ' ' . $font['n'][$k] . ' 0 R'); + } + } else { + $this->writer->write('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + } + } + $this->writer->write('>>'); + + if (count($this->mpdf->spotColors)) { + $this->writer->write('/ColorSpace <<'); + foreach ($this->mpdf->spotColors as $color) { + $this->writer->write('/CS' . $color['i'] . ' ' . $color['n'] . ' 0 R'); + } + $this->writer->write('>>'); + } + + if (count($this->mpdf->extgstates)) { + $this->writer->write('/ExtGState <<'); + foreach ($this->mpdf->extgstates as $k => $extgstate) { + if (isset($extgstate['trans'])) { + $this->writer->write('/' . $extgstate['trans'] . ' ' . $extgstate['n'] . ' 0 R'); + } else { + $this->writer->write('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R'); + } + } + $this->writer->write('>>'); + } + + /* -- BACKGROUNDS -- */ + if (($this->mpdf->gradients !== null && (count($this->mpdf->gradients) > 0))) { // mPDF 5.7.3 + + $this->writer->write('/Shading <<'); + + foreach ($this->mpdf->gradients as $id => $grad) { + $this->writer->write('/Sh' . $id . ' ' . $grad['id'] . ' 0 R'); + } + + $this->writer->write('>>'); + + /* + // ??? Not needed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + $this->writer->write('/Pattern <<'); + foreach ($this->mpdf->gradients as $id => $grad) { + $this->writer->write('/P'.$id.' '.$grad['pattern'].' 0 R'); + } + $this->writer->write('>>'); + */ + } + /* -- END BACKGROUNDS -- */ + + if (count($this->mpdf->images) || count($this->mpdf->formobjects) || count($this->mpdf->getImportedPages())) { + $this->writer->write('/XObject <<'); + foreach ($this->mpdf->images as $image) { + $this->writer->write('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + } + foreach ($this->mpdf->formobjects as $formobject) { + $this->writer->write('/FO' . $formobject['i'] . ' ' . $formobject['n'] . ' 0 R'); + } + /* -- IMPORTS -- */ + foreach ($this->mpdf->getImportedPages() as $pageData) { + $this->writer->write('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); + } + /* -- END IMPORTS -- */ + $this->writer->write('>>'); + } + + /* -- BACKGROUNDS -- */ + + if (count($this->mpdf->patterns)) { + $this->writer->write('/Pattern <<'); + foreach ($this->mpdf->patterns as $k => $patterns) { + $this->writer->write('/P' . $k . ' ' . $patterns['n'] . ' 0 R'); + } + $this->writer->write('>>'); + } + /* -- END BACKGROUNDS -- */ + + if ($this->mpdf->hasOC || count($this->mpdf->layers)) { + $this->writer->write('/Properties <<'); + if ($this->mpdf->hasOC) { + $this->writer->write('/OC1 ' . $this->mpdf->n_ocg_print . ' 0 R /OC2 ' . $this->mpdf->n_ocg_view . ' 0 R /OC3 ' . $this->mpdf->n_ocg_hidden . ' 0 R '); + } + if (count($this->mpdf->layers)) { + foreach ($this->mpdf->layers as $id => $layer) { + $this->writer->write('/ZI' . $id . ' ' . $layer['n'] . ' 0 R'); + } + } + $this->writer->write('>>'); + } + + $this->writer->write('>>'); + $this->writer->write('endobj'); // end resource dictionary + + $this->bookmarkWriter->writeBookmarks(); + + if (!empty($this->mpdf->js)) { + $this->javaScriptWriter->writeJavascript(); + } + + if ($this->mpdf->encrypted) { + $this->writer->object(); + $this->mpdf->enc_obj_id = $this->mpdf->n; + $this->writer->write('<<'); + $this->metadataWriter->writeEncryption(); + $this->writer->write('>>'); + $this->writer->write('endobj'); + } + } +} diff --git a/src/vendor/mpdf/mpdf/src/functions-dev.php b/src/vendor/mpdf/mpdf/src/functions-dev.php new file mode 100644 index 000000000..355f3e3fd --- /dev/null +++ b/src/vendor/mpdf/mpdf/src/functions-dev.php @@ -0,0 +1,13 @@ + is used for editing the fonts. + +Design Issues +------------- + +Which font shapes should be made? Historical style terms like Renaissance +or Baroque letterforms cannot be applied beyond Latin/Cyrillic/Greek +scripts to any greater extent than Kufi or Nashki can be applied beyond +Arabic script; "italic" is really only meaningful for Latin letters. + +However, most modern writing systems have typographic formulations for +contrasting uniform and modulated character stroke widths, and have some +history with "oblique", faces. Since the advent of the typewriter, most +have developed a typographic style with uniform-width characters. + +Accordingly, the FreeFont family has one monospaced - FreeMono - and two +proportional faces (one with uniform stroke - FreeSans - and one with +modulated stroke - FreeSerif). + +To make text from different writing systems look good side-by-side, each +FreeFont face is meant to contain characters of similar style and weight. + +Licensing +--------- + +Free UCS scalable fonts is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +The fonts are distributed in the hope that they will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +As a special exception, if you create a document which uses this font, and +embed this font or unaltered portions of this font into the document, this +font does not by itself cause the resulting document to be covered by the +GNU General Public License. This exception does not however invalidate any +other reasons why the document might be covered by the GNU General Public +License. If you modify this font, you may extend this exception to your +version of the font, but you are not obligated to do so. If you do not +wish to do so, delete this exception statement from your version. + + +Files and their suffixes +------------------------ + +The files with .sfd (Spline Font Database) are in FontForge's native format. +Please use these if you plan to modify the font files. + +TrueType fonts for immediate consumption are the files with the .ttf +(TrueType Font) suffix. These are ready to use in Xwindows based +systems using FreeType, on Mac OS, and on older Windows systems. + +OpenType fonts (with suffix .otf) are for use in Windows Vista. +Note that although they can be installed on Linux, but many applications +in Linux still don't support them. + + +-------------------------------------------------------------------------- +Primoz Peterlin, +Steve White + +Free UCS scalable fonts: http://savannah.gnu.org/projects/freefont/ +$Id: README,v 1.6 2008/12/25 12:51:41 Stevan_White Exp $ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Garuda-Bold.ttf b/src/vendor/mpdf/mpdf/ttfonts/Garuda-Bold.ttf new file mode 100644 index 000000000..c2aa87edb Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Garuda-Bold.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Garuda-BoldOblique.ttf b/src/vendor/mpdf/mpdf/ttfonts/Garuda-BoldOblique.ttf new file mode 100644 index 000000000..889be702a Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Garuda-BoldOblique.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Garuda-Oblique.ttf b/src/vendor/mpdf/mpdf/ttfonts/Garuda-Oblique.ttf new file mode 100644 index 000000000..7d1219907 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Garuda-Oblique.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Garuda.ttf b/src/vendor/mpdf/mpdf/ttfonts/Garuda.ttf new file mode 100644 index 000000000..0abddd354 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Garuda.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Jomolhari-OFL.txt b/src/vendor/mpdf/mpdf/ttfonts/Jomolhari-OFL.txt new file mode 100644 index 000000000..b723c35f6 --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/Jomolhari-OFL.txt @@ -0,0 +1,98 @@ +This Font Software is Copyright (c) 2006, Christopher J Fynn +All Rights Reserved. + +"Jomolhari" is a Reserved Font Name for this Font Software. + +This Font Software is licensed under the SIL Open Font License, Version 1.0. +No modification of the license is permitted, only verbatim copy is allowed. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.0 - 22 November 2005 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of cooperative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide an open +framework in which fonts may be shared and improved in partnership with +others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and sold with any software provided that the font +names of derivative works are changed. The fonts and derivatives, +however, cannot be released under any other type of license. + +DEFINITIONS +"Font Software" refers to any and all of the following: + - font files + - data files + - source code + - build scripts + - documentation + +"Reserved Font Name" refers to the Font Software name as seen by +users and any other names as specified after the copyright statement. + +"Standard Version" refers to the collection of Font Software +components as distributed by the Copyright Holder. + +"Modified Version" refers to any derivative font software made by +adding to, deleting, or substituting -- in part or in whole -- +any of the components of the Standard Version, by changing formats +or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Standard or Modified Versions, may be sold by itself. + +2) Standard or Modified Versions of the Font Software may be bundled, +redistributed and sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s), in part or in whole, unless explicit written permission is +granted by the Copyright Holder. This restriction applies to all +references stored in the Font Software, such as the font menu name and +other font description fields, which are used to differentiate the +font from others. + +4) The name(s) of the Copyright Holder or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed using this license, and may not be distributed +under any other license. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/Jomolhari.ttf b/src/vendor/mpdf/mpdf/ttfonts/Jomolhari.ttf new file mode 100644 index 000000000..ca695b61d Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Jomolhari.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/KhmerOFL.txt b/src/vendor/mpdf/mpdf/ttfonts/KhmerOFL.txt new file mode 100644 index 000000000..bfa6ae45c --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/KhmerOFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010, Danh Hong (khmertype.blogspot.com), +with Reserved Font Name Khmer. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/KhmerOS.ttf b/src/vendor/mpdf/mpdf/ttfonts/KhmerOS.ttf new file mode 100644 index 000000000..7aa5bdcd5 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/KhmerOS.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Lateef font OFL.txt b/src/vendor/mpdf/mpdf/ttfonts/Lateef font OFL.txt new file mode 100644 index 000000000..7a1b1c7e4 --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/Lateef font OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2004-2011, SIL International (http://www.sil.org/), +with Reserved Font Names "Scheherazade" and "SIL". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/LateefRegOT.ttf b/src/vendor/mpdf/mpdf/ttfonts/LateefRegOT.ttf new file mode 100644 index 000000000..f89d32be3 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/LateefRegOT.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Lohit-Kannada.ttf b/src/vendor/mpdf/mpdf/ttfonts/Lohit-Kannada.ttf new file mode 100644 index 000000000..2911ce7b6 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Lohit-Kannada.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/LohitKannadaOFL.txt b/src/vendor/mpdf/mpdf/ttfonts/LohitKannadaOFL.txt new file mode 100644 index 000000000..01b830782 --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/LohitKannadaOFL.txt @@ -0,0 +1,94 @@ +Copyright 2011-12 Lohit Fonts Project contributors + + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/Padauk-book.ttf b/src/vendor/mpdf/mpdf/ttfonts/Padauk-book.ttf new file mode 100644 index 000000000..590cdadd4 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Padauk-book.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Pothana2000.ttf b/src/vendor/mpdf/mpdf/ttfonts/Pothana2000.ttf new file mode 100644 index 000000000..296d7d665 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Pothana2000.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Quivira.otf b/src/vendor/mpdf/mpdf/ttfonts/Quivira.otf new file mode 100644 index 000000000..531edf16c Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Quivira.otf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtA.ttf b/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtA.ttf new file mode 100644 index 000000000..1c9c2cfa5 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtA.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtB.ttf b/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtB.ttf new file mode 100644 index 000000000..8a53b20c5 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Sun-ExtB.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/SundaneseUnicode-1.0.5.ttf b/src/vendor/mpdf/mpdf/ttfonts/SundaneseUnicode-1.0.5.ttf new file mode 100644 index 000000000..a86b47578 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/SundaneseUnicode-1.0.5.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa.otf b/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa.otf new file mode 100644 index 000000000..9e1fbda08 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa.otf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa_license.txt b/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa_license.txt new file mode 100644 index 000000000..35c74dddc --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/SyrCOMEdessa_license.txt @@ -0,0 +1,61 @@ +This license is derived from the Bigelow & Holmes Font License +found at http://www.xfree86.org/current/LICENSE2.html + +The following reasonable modifications have been made to the +Bigelow & Holmes Font License: + +* All references to Luxi have been replaced with Meltho + +* All references to Bigelow & Holmes Inc. and URW++ GmbH haven + been replaced with Beth Mardutho: The Syriac Institute + +* The registered trademark notice belonging to Bigelow & Holmes + Inc. has been removed + +* Contact information has been modified to show that the + contact person for these fonts is the Director of the + Institute, George Kiraz. + +------------------------------------------------------------- + +Meltho fonts and font code copyright © 2002 by Beth Mardutho: +The Syriac Institute. All Right Reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of these Fonts and associated documentation +files (the "Font Software"), to deal in the Font Software, +including without limitation the rights to use, copy, merge, +publish, distribute, sublicense, and/or sell copies of the +Font Software, and to permit persons to whom the Font Software +is furnished to do so, subject to the following conditions: + +The above copyright and trademark notices and this permission +notice shall be included in all copies of one or more of the +Font Software. + +The Font Software may not be modified, altered, or added to, +and in particular the designs of glyphs or characters in the +Fonts may not be modified nor may additional glyphs or +characters be added to the Fonts. This License becomes null +and void when the Fonts or Font Software have been modified. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER +RIGHT. IN NO EVENT SHALL BETH MARDUTHO: THE SYRIAC INSTITUTE BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY +GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR +FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Beth Mardutho: +The Syriac Institute shall not be used in advertising or otherwise +to promote the sale, use or other dealings in this Font Software +without prior written authorization from Beth Mardutho: The +Syriac Institute. + +For further information, contact: +George Kiraz, Director of Beth Mardutho +gkiraz@bethmardutho.org diff --git a/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-LICENSE.txt b/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-LICENSE.txt new file mode 100644 index 000000000..de1ef6320 --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-LICENSE.txt @@ -0,0 +1,17 @@ +This package is distributed under the terms of GNU General Public License +version 2 (see file GNU-GPL). +--------------------------------------------------------------------- + +"Taamey David CLM" fonts are copyright (C) 2010 by Yoram Gnat +(gyoramg@users.sourceforge.net). All rights reserved. + +As a special exception, if you create a document which uses +this font, and embed this font or unaltered portions of this +font into the document, this font does not by itself cause +the resulting document to be covered by the +GNU General Public License. This exception does not however +invalidate any other reasons why the document might be covered +by the GNU General Public License. If you modify this font, +you may extend this exception to your version of the font, +but you are not obligated to do so. If you do not wish to do so, +delete this exception statement from your version. diff --git a/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-Medium.ttf b/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-Medium.ttf new file mode 100644 index 000000000..2aed6f85e Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/TaameyDavidCLM-Medium.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/TaiHeritagePro.ttf b/src/vendor/mpdf/mpdf/ttfonts/TaiHeritagePro.ttf new file mode 100644 index 000000000..d4ed9538b Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/TaiHeritagePro.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Tharlon-Regular.ttf b/src/vendor/mpdf/mpdf/ttfonts/Tharlon-Regular.ttf new file mode 100644 index 000000000..4717d70cd Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Tharlon-Regular.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/TharlonOFL.txt b/src/vendor/mpdf/mpdf/ttfonts/TharlonOFL.txt new file mode 100644 index 000000000..2973d5df3 --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/TharlonOFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010-2012, Sai Zin Di Di Zone (www.yunghkio.com/unicode|saiddzone@gmail.com), with Reserved Font Name 'Yunghkio'. Copyright (c) 2012, Google, Inc (http://code.google.com/p/googlefontdirectory/), with Reserved Font Name 'Arimo'. Copyright (c) 2012, Sun Tun, Ngwe Tun, Solveware Solution (http://code.google.com/p/tharlon-font|info@parabaik.info), with Reserved Font Name 'TharLon'. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/UnBatang_0613.ttf b/src/vendor/mpdf/mpdf/ttfonts/UnBatang_0613.ttf new file mode 100644 index 000000000..2e93d5f86 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/UnBatang_0613.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/Uthman.otf b/src/vendor/mpdf/mpdf/ttfonts/Uthman.otf new file mode 100644 index 000000000..bb650a24e Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/Uthman.otf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/XB Riyaz.ttf b/src/vendor/mpdf/mpdf/ttfonts/XB Riyaz.ttf new file mode 100644 index 000000000..80e15803d Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/XB Riyaz.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBd.ttf b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBd.ttf new file mode 100644 index 000000000..e6cf58f93 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBd.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBdIt.ttf b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBdIt.ttf new file mode 100644 index 000000000..19fba7887 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazBdIt.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/XB RiyazIt.ttf b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazIt.ttf new file mode 100644 index 000000000..cc9cc3ab2 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/XB RiyazIt.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/XW Zar Font Info.txt b/src/vendor/mpdf/mpdf/ttfonts/XW Zar Font Info.txt new file mode 100644 index 000000000..d42e4544b --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/XW Zar Font Info.txt @@ -0,0 +1,92 @@ + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/vendor/mpdf/mpdf/ttfonts/ZawgyiOne.ttf b/src/vendor/mpdf/mpdf/ttfonts/ZawgyiOne.ttf new file mode 100644 index 000000000..573147158 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/ZawgyiOne.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/ayar.ttf b/src/vendor/mpdf/mpdf/ttfonts/ayar.ttf new file mode 100644 index 000000000..e74c61204 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/ayar.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/damase_v.2.ttf b/src/vendor/mpdf/mpdf/ttfonts/damase_v.2.ttf new file mode 100644 index 000000000..a60240bab Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/damase_v.2.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/kaputaunicode.ttf b/src/vendor/mpdf/mpdf/ttfonts/kaputaunicode.ttf new file mode 100644 index 000000000..fe0269726 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/kaputaunicode.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/lannaalif-v1-03.ttf b/src/vendor/mpdf/mpdf/ttfonts/lannaalif-v1-03.ttf new file mode 100644 index 000000000..7c20d9791 Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/lannaalif-v1-03.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/ocrb10.ttf b/src/vendor/mpdf/mpdf/ttfonts/ocrb10.ttf new file mode 100644 index 000000000..34980b80c Binary files /dev/null and b/src/vendor/mpdf/mpdf/ttfonts/ocrb10.ttf differ diff --git a/src/vendor/mpdf/mpdf/ttfonts/ocrbinfo.txt b/src/vendor/mpdf/mpdf/ttfonts/ocrbinfo.txt new file mode 100644 index 000000000..c2dd9954c --- /dev/null +++ b/src/vendor/mpdf/mpdf/ttfonts/ocrbinfo.txt @@ -0,0 +1,60 @@ +Mostly-free OCR B + +This font is used in UPC bar code symbols, including the ISBN symbols on +most published books. + +A freely distributable version seems to be sorely needed. Until now, it's +been very difficult to find the font in computer-usable format except by +paying a high fee to a commercial font vendor. Even many serious commercial +publishers have so much trouble getting it right that they just go ahead and +use Helvetica instead, or even (shudder) Arial. Since the OCR B font is +required by an international standard, it seems like it ought to be free. +So here it is. The font in this package is not a "ripped", pirated, or +shadily reverse engineered version; every effort has been made to ensure +that it genuinely derives from free sources and all the creators involved +have actually intended it for free public use. + +Converted by Matthew Skala from Metafont format to Postscript and TrueType +formats, July 28, 2006, using mftrace 1.2.4 by Paul Vojta, which is +available from + http://www.xs4all.nl/~hanwen/mftrace/ +and Autotrace 0.31.1 available from + http://autotrace.sourceforge.net/ + +The Metafont files (not included - see notes below) were coded by Norbert +Schwarz in the 1980s, based on German standards documents. He has attached +a notice, notably not actually claiming any copyright - see the file +"ocrbinfo" - saying that the fonts are "given to free non commercial use", +but commenting that he is only free to grant rights to his own work on the +digitization, because he did not design the original letter forms. He +suggests that there may be other copyright claims attached to the letter +forms themselves, which Schwarz credits as being originally designed by +"Adam Frutiger" [sic], almost certainly a mistake for Adrian Frutiger. My +(Matthew Skala's) understanding of copyright law, at least in the USA and +Canada, is that in fact typefaces per se cannot be subject to copyright +claims, so the software embodiment is the only thing subject to copyright +and Schwarz's release makes it available for whatever "non commercial use" +means. + +To avoid muddying the waters further, any copyright claims by Matthew Skala +on these files are hereby released to the public domain. I'd like for these +fonts to be freely usable even in marginally commercial applications, such +as to generate UPC labels for books that will be sold for profit, but it may +not be within my power to grant that myself because I didn't write the +Metafont files although I did do considerable, and probably copyrightable, +work on the translation to Postscript and TrueType. It was *not* a purely +automated process; try using the tools I used and see how far you get +without human editing! I'd also like for these fonts (the fonts themselves +as opposed to documents made with them) not to be sold, not even indirectly +by those Web sites that advertise "free downloads" but make it difficult to +actually download fonts without paying a fee. + +NOTE: This ZIP archive is a stripped-down version containing just the +essential files for using the main OCR B font on most systems. If you want +the much larger complete package, which contains Metafont sources and several +variant fonts (reverse-video, outline, and slanted), look for a ZIP archive +called ocrb-complete.zip wherever you found this one. + +Matthew Skala +mskala@ansuz.sooke.bc.ca +http://ansuz.sooke.bc.ca/ diff --git a/src/vendor/mpdf/psr-http-message-shim/README.md b/src/vendor/mpdf/psr-http-message-shim/README.md new file mode 100644 index 000000000..3efdcb835 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/README.md @@ -0,0 +1,16 @@ +# psr-http-message-shim + +Trait to allow support of different psr/http-message versions. + +Based on the psr-log-aware-trait, developed by Matěj Humpál, K Widholm and Mark Dorison. + +By including this shim, you can allow composer to resolve your Psr\Http\Message version for you. + +## Use + +Require the shim. + + composer require mpdf/psr-http-message-shim + +Modify any use of mpdf's Request.php, Response.php, Stream.php and Uri.php classes to instead use versions +from the Mpdf\HttpMessageShim namespace. diff --git a/src/vendor/mpdf/psr-http-message-shim/composer.json b/src/vendor/mpdf/psr-http-message-shim/composer.json new file mode 100644 index 000000000..b8394e7e9 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/composer.json @@ -0,0 +1,28 @@ +{ + "name": "mpdf/psr-http-message-shim", + "description": "Shim to allow support of different psr/message versions.", + "type": "library", + "require": { + "psr/http-message": "^1.0" + }, + "license": "MIT", + "autoload": { + "psr-4": { + "Mpdf\\PsrHttpMessageShim\\": "src/" + } + }, + "authors": [ + { + "name": "Mark Dorison", + "email": "mark@chromatichq.com" + }, + { + "name": "Kristofer Widholm", + "email": "kristofer@chromatichq.com" + }, + { + "name": "Nigel Cunningham", + "email": "nigel.cunningham@technocrat.com.au" + } + ] +} diff --git a/src/vendor/mpdf/psr-http-message-shim/src/Request.php b/src/vendor/mpdf/psr-http-message-shim/src/Request.php new file mode 100644 index 000000000..30575cc51 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/src/Request.php @@ -0,0 +1,319 @@ + array of values */ + private $headers = []; + + /** @var array Map of lowercase header name => original name at registration */ + private $headerNames = []; + + /** @var string */ + private $protocol; + + /** @var StreamInterface */ + private $stream; + + /** + * @param string $method HTTP method + * @param string|UriInterface $uri URI + * @param array $headers Request headers + * @param string|null|resource|StreamInterface $body Request body + * @param string $version Protocol version + */ + public function __construct( + $method, + $uri, + array $headers = [], + $body = null, + $version = '1.1' + ) { + if (!($uri instanceof UriInterface)) { + $uri = new Uri($uri); + } + + $this->method = $method; + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + + if (!$this->hasHeader('Host')) { + $this->updateHostFromUri(); + } + + if ($body !== '' && $body !== null) { + $this->stream = Stream::create($body); + } + } + + public function getRequestTarget() + { + if ($this->requestTarget !== null) { + return $this->requestTarget; + } + + $target = $this->uri->getPath(); + if ($target == '') { + $target = '/'; + } + if ($this->uri->getQuery() != '') { + $target .= '?'.$this->uri->getQuery(); + } + + return $target; + } + + public function withRequestTarget($requestTarget) + { + if (preg_match('#\s#', $requestTarget)) { + throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace'); + } + + $new = clone $this; + $new->requestTarget = $requestTarget; + + return $new; + } + + public function getMethod() + { + return $this->method; + } + + public function withMethod($method) + { + $new = clone $this; + $new->method = $method; + + return $new; + } + + public function getUri() + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false) + { + if ($uri === $this->uri) { + return $this; + } + + $new = clone $this; + $new->uri = $uri; + + if (!$preserveHost || !$this->hasHeader('Host')) { + $new->updateHostFromUri(); + } + + return $new; + } + + private function updateHostFromUri() + { + $host = $this->uri->getHost(); + + if ($host == '') { + return; + } + + if (($port = $this->uri->getPort()) !== null) { + $host .= ':'.$port; + } + + if (isset($this->headerNames['host'])) { + $header = $this->headerNames['host']; + } else { + $header = 'Host'; + $this->headerNames['host'] = 'Host'; + } + // Ensure Host is the first header. + // See: http://tools.ietf.org/html/rfc7230#section-5.4 + $this->headers = [$header => [$host]] + $this->headers; + } + + public function getProtocolVersion() + { + return $this->protocol; + } + + public function withProtocolVersion($version) + { + if ($this->protocol === $version) { + return $this; + } + + $new = clone $this; + $new->protocol = $version; + + return $new; + } + + public function getHeaders() + { + return $this->headers; + } + + public function hasHeader($header) + { + return isset($this->headerNames[strtolower($header)]); + } + + public function getHeader($header) + { + $header = strtolower($header); + + if (!isset($this->headerNames[$header])) { + return []; + } + + $header = $this->headerNames[$header]; + + return $this->headers[$header]; + } + + public function getHeaderLine($header) + { + return implode(', ', $this->getHeader($header)); + } + + public function withHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + unset($new->headers[$new->headerNames[$normalized]]); + } + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + + return $new; + } + + public function withAddedHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $new->headers[$header] = array_merge($this->headers[$header], $value); + } else { + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + } + + return $new; + } + + public function withoutHeader($header) + { + $normalized = strtolower($header); + + if (!isset($this->headerNames[$normalized])) { + return $this; + } + + $header = $this->headerNames[$normalized]; + + $new = clone $this; + unset($new->headers[$header], $new->headerNames[$normalized]); + + return $new; + } + + public function getBody() + { + if (!$this->stream) { + $this->stream = Stream::create(''); + $this->stream->rewind(); + } + + return $this->stream; + } + + public function withBody(StreamInterface $body) + { + if ($body === $this->stream) { + return $this; + } + + $new = clone $this; + $new->stream = $body; + + return $new; + } + + private function setHeaders(array $headers) + { + $this->headerNames = $this->headers = []; + foreach ($headers as $header => $value) { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + } + } + + /** + * Trims whitespace from the header values. + * + * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. + * + * header-field = field-name ":" OWS field-value OWS + * OWS = *( SP / HTAB ) + * + * @param string[] $values Header values + * + * @return string[] Trimmed header values + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + */ + private function trimHeaderValues(array $values) + { + return array_map(function ($value) { + return trim($value, " \t"); + }, $values); + } + +} diff --git a/src/vendor/mpdf/psr-http-message-shim/src/Response.php b/src/vendor/mpdf/psr-http-message-shim/src/Response.php new file mode 100644 index 000000000..731664dd9 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/src/Response.php @@ -0,0 +1,261 @@ + 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', + 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', + 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', + 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', + 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required', + ]; + + /** @var string */ + private $reasonPhrase; + + /** @var int */ + private $statusCode; + + /** @var array Map of all registered headers, as original name => array of values */ + private $headers = []; + + /** @var array Map of lowercase header name => original name at registration */ + private $headerNames = []; + + /** @var string */ + private $protocol; + + /** @var \Psr\Http\Message\StreamInterface */ + private $stream; + + /** + * @param int $status Status code + * @param array $headers Response headers + * @param string|resource|StreamInterface|null $body Response body + * @param string $version Protocol version + * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) + */ + public function __construct($status = 200, array $headers = [], $body = null, $version = '1.1', $reason = null) + { + // If we got no body, defer initialization of the stream until Response::getBody() + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + + $this->statusCode = $status; + $this->setHeaders($headers); + if (null === $reason && isset(self::$phrases[$this->statusCode])) { + $this->reasonPhrase = self::$phrases[$status]; + } else { + $this->reasonPhrase = isset($reason) ? $reason : ''; + } + + $this->protocol = $version; + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + + public function withStatus($code, $reasonPhrase = '') + { + if (!\is_int($code) && !\is_string($code)) { + throw new \InvalidArgumentException('Status code has to be an integer'); + } + + $code = (int) $code; + if ($code < 100 || $code > 599) { + throw new \InvalidArgumentException(\sprintf('Status code has to be an integer between 100 and 599. A status code of %d was given', $code)); + } + + $new = clone $this; + $new->statusCode = $code; + if ((null === $reasonPhrase || '' === $reasonPhrase) && isset(self::$phrases[$new->statusCode])) { + $reasonPhrase = self::$phrases[$new->statusCode]; + } + $new->reasonPhrase = $reasonPhrase; + + return $new; + } + + public function getProtocolVersion() + { + return $this->protocol; + } + + public function withProtocolVersion($version) + { + if ($this->protocol === $version) { + return $this; + } + + $new = clone $this; + $new->protocol = $version; + + return $new; + } + + public function getHeaders() + { + return $this->headers; + } + + public function hasHeader($header) + { + return isset($this->headerNames[strtolower($header)]); + } + + public function getHeader($header) + { + $header = strtolower($header); + + if (!isset($this->headerNames[$header])) { + return []; + } + + $header = $this->headerNames[$header]; + + return $this->headers[$header]; + } + + public function getHeaderLine($header) + { + return implode(', ', $this->getHeader($header)); + } + + public function withHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + unset($new->headers[$new->headerNames[$normalized]]); + } + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + + return $new; + } + + public function withAddedHeader($header, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $new->headers[$header] = array_merge($this->headers[$header], $value); + } else { + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + } + + return $new; + } + + public function withoutHeader($header) + { + $normalized = strtolower($header); + + if (!isset($this->headerNames[$normalized])) { + return $this; + } + + $header = $this->headerNames[$normalized]; + + $new = clone $this; + unset($new->headers[$header], $new->headerNames[$normalized]); + + return $new; + } + + public function getBody() + { + if (!$this->stream) { + $this->stream = Stream::create(''); + } + + return $this->stream; + } + + public function withBody(StreamInterface $body) + { + if ($body === $this->stream) { + return $this; + } + + $new = clone $this; + $new->stream = $body; + + return $new; + } + + private function setHeaders(array $headers) + { + $this->headerNames = $this->headers = []; + foreach ($headers as $header => $value) { + if (!is_array($value)) { + $value = [$value]; + } + + $value = $this->trimHeaderValues($value); + $normalized = strtolower($header); + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + } + } + + /** + * Trims whitespace from the header values. + * + * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. + * + * header-field = field-name ":" OWS field-value OWS + * OWS = *( SP / HTAB ) + * + * @param string[] $values Header values + * + * @return string[] Trimmed header values + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + */ + private function trimHeaderValues(array $values) + { + return array_map(function ($value) { + return trim($value, " \t"); + }, $values); + } + +} diff --git a/src/vendor/mpdf/psr-http-message-shim/src/Stream.php b/src/vendor/mpdf/psr-http-message-shim/src/Stream.php new file mode 100644 index 000000000..d8170d0c0 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/src/Stream.php @@ -0,0 +1,270 @@ + [ + 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, + 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a+' => true, + ], + 'write' => [ + 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, + 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, + 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true, + ], + ]; + + private function __construct() + { + } + + /** + * @param resource $resource + * + * @return Stream + */ + public static function createFromResource($resource) + { + if (!is_resource($resource)) { + throw new \InvalidArgumentException('Stream must be a resource'); + } + + $obj = new self(); + $obj->stream = $resource; + $meta = stream_get_meta_data($obj->stream); + $obj->seekable = $meta['seekable']; + $obj->readable = isset(self::$readWriteHash['read'][$meta['mode']]); + $obj->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $obj->uri = $obj->getMetadata('uri'); + + return $obj; + } + + /** + * @param string $content + * + * @return Stream + */ + public static function create($content) + { + $resource = fopen('php://temp', 'rwb+'); + $stream = self::createFromResource($resource); + $stream->write($content); + $stream->seek(0); + + return $stream; + } + + /** + * Closes the stream when the destructed. + */ + public function __destruct() + { + $this->close(); + } + + public function __toString() + { + try { + if ($this->isSeekable()) { + $this->seek(0); + } + + return $this->getContents(); + } catch (\Exception $e) { + return ''; + } + } + + public function close() + { + if (isset($this->stream)) { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->detach(); + } + } + + public function detach() + { + if (!isset($this->stream)) { + return; + } + + $result = $this->stream; + unset($this->stream); + $this->size = $this->uri = null; + $this->readable = $this->writable = $this->seekable = false; + + return $result; + } + + public function getSize() + { + if ($this->size !== null) { + return $this->size; + } + + if (!isset($this->stream)) { + return; + } + + // Clear the stat cache if the stream has a URI + if ($this->uri) { + clearstatcache(true, $this->uri); + } + + $stats = fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + + return $this->size; + } + } + + public function tell() + { + $result = ftell($this->stream); + + if ($result === false) { + throw new \RuntimeException('Unable to determine stream position'); + } + + return $result; + } + + public function eof() + { + return !$this->stream || feof($this->stream); + } + + public function isSeekable() + { + return $this->seekable; + } + + public function seek($offset, $whence = SEEK_SET) + { + if (!$this->seekable) { + throw new \RuntimeException('Stream is not seekable'); + } + + if (fseek($this->stream, $offset, $whence) === -1) { + throw new \RuntimeException('Unable to seek to stream position '.$offset.' with whence '.var_export($whence, true)); + } + } + + public function rewind() + { + $this->seek(0); + } + + public function isWritable() + { + return $this->writable; + } + + public function write($string) + { + if (!$this->writable) { + throw new \RuntimeException('Cannot write to a non-writable stream'); + } + + // We can't know the size after writing anything + $this->size = null; + $result = fwrite($this->stream, $string); + + if ($result === false) { + throw new \RuntimeException('Unable to write to stream'); + } + + return $result; + } + + public function isReadable() + { + return $this->readable; + } + + public function read($length) + { + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); + } + + return fread($this->stream, $length); + } + + public function getContents() + { + if (!isset($this->stream)) { + throw new \RuntimeException('Unable to read stream contents'); + } + + $contents = stream_get_contents($this->stream); + + if ($contents === false) { + throw new \RuntimeException('Unable to read stream contents'); + } + + return $contents; + } + + public function getMetadata($key = null) + { + if (!isset($this->stream)) { + return $key ? null : []; + } + + if ($key === null) { + return stream_get_meta_data($this->stream); + } + + $meta = stream_get_meta_data($this->stream); + + return isset($meta[$key]) ? $meta[$key] : null; + } + +} diff --git a/src/vendor/mpdf/psr-http-message-shim/src/Uri.php b/src/vendor/mpdf/psr-http-message-shim/src/Uri.php new file mode 100644 index 000000000..8bb260f14 --- /dev/null +++ b/src/vendor/mpdf/psr-http-message-shim/src/Uri.php @@ -0,0 +1,303 @@ + 80, 'https' => 443]; + + const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; + + const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; + + /** @var string Uri scheme. */ + private $scheme = ''; + + /** @var string Uri user info. */ + private $userInfo = ''; + + /** @var string Uri host. */ + private $host = ''; + + /** @var int|null Uri port. */ + private $port; + + /** @var string Uri path. */ + private $path = ''; + + /** @var string Uri query string. */ + private $query = ''; + + /** @var string Uri fragment. */ + private $fragment = ''; + + public function __construct($uri = '') + { + if ('' !== $uri) { + if (false === $parts = \parse_url($uri)) { + throw new \InvalidArgumentException(\sprintf('Unable to parse URI: "%s"', $uri)); + } + + // Apply parse_url parts to a URI. + $this->scheme = isset($parts['scheme']) ? \strtr($parts['scheme'], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : ''; + $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->host = isset($parts['host']) ? \strtr($parts['host'], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : ''; + $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; + $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; + $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; + $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; + if (isset($parts['pass'])) { + $this->userInfo .= ':' . $parts['pass']; + } + } + } + + public function __toString() + { + return self::createUriString($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); + } + + public function getScheme() + { + return $this->scheme; + } + + public function getAuthority() + { + if ('' === $this->host) { + return ''; + } + + $authority = $this->host; + if ('' !== $this->userInfo) { + $authority = $this->userInfo . '@' . $authority; + } + + if (null !== $this->port) { + $authority .= ':' . $this->port; + } + + return $authority; + } + + public function getUserInfo() + { + return $this->userInfo; + } + + public function getHost() + { + return $this->host; + } + + public function getPort() + { + return $this->port; + } + + public function getPath() + { + return $this->path; + } + + public function getQuery() + { + return $this->query; + } + + public function getFragment() + { + return $this->fragment; + } + + public function withScheme($scheme) + { + if (!\is_string($scheme)) { + throw new \InvalidArgumentException('Scheme must be a string'); + } + + if ($this->scheme === $scheme = \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')) { + return $this; + } + + $new = clone $this; + $new->scheme = $scheme; + $new->port = $new->filterPort($new->port); + + return $new; + } + + public function withUserInfo($user, $password = null) + { + $info = $user; + if (null !== $password && '' !== $password) { + $info .= ':' . $password; + } + + if ($this->userInfo === $info) { + return $this; + } + + $new = clone $this; + $new->userInfo = $info; + + return $new; + } + + public function withHost($host) + { + if (!\is_string($host)) { + throw new \InvalidArgumentException('Host must be a string'); + } + + if ($this->host === $host = \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')) { + return $this; + } + + $new = clone $this; + $new->host = $host; + + return $new; + } + + public function withPort($port) + { + if ($this->port === $port = $this->filterPort($port)) { + return $this; + } + + $new = clone $this; + $new->port = $port; + + return $new; + } + + public function withPath($path) + { + if ($this->path === $path = $this->filterPath($path)) { + return $this; + } + + $new = clone $this; + $new->path = $path; + + return $new; + } + + public function withQuery($query) + { + if ($this->query === $query = $this->filterQueryAndFragment($query)) { + return $this; + } + + $new = clone $this; + $new->query = $query; + + return $new; + } + + public function withFragment($fragment) + { + if ($this->fragment === $fragment = $this->filterQueryAndFragment($fragment)) { + return $this; + } + + $new = clone $this; + $new->fragment = $fragment; + + return $new; + } + + /** + * Create a URI string from its various parts. + */ + private static function createUriString($scheme, $authority, $path, $query, $fragment) + { + $uri = ''; + if ('' !== $scheme) { + $uri .= $scheme . ':'; + } + + if ('' !== $authority) { + $uri .= '//' . $authority; + } + + if ('' !== $path) { + if ('/' !== $path[0]) { + if ('' !== $authority) { + // If the path is rootless and an authority is present, the path MUST be prefixed by "/" + $path = '/' . $path; + } + } elseif (isset($path[1]) && '/' === $path[1]) { + if ('' === $authority) { + // If the path is starting with more than one "/" and no authority is present, the + // starting slashes MUST be reduced to one. + $path = '/' . \ltrim($path, '/'); + } + } + + $uri .= $path; + } + + if ('' !== $query) { + $uri .= '?' . $query; + } + + if ('' !== $fragment) { + $uri .= '#' . $fragment; + } + + return $uri; + } + + /** + * Is a given port non-standard for the current scheme? + */ + private static function isNonStandardPort($scheme, $port) + { + return !isset(self::$schemes[$scheme]) || $port !== self::$schemes[$scheme]; + } + + private function filterPort($port) + { + if (null === $port) { + return null; + } + + $port = (int) $port; + if (0 > $port || 0xffff < $port) { + throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 0 and 65535', $port)); + } + + return self::isNonStandardPort($this->scheme, $port) ? $port : null; + } + + private function filterPath($path) + { + if (!\is_string($path)) { + throw new \InvalidArgumentException('Path must be a string'); + } + + return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [__CLASS__, 'rawurlencodeMatchZero'], $path); + } + + private function filterQueryAndFragment($str) + { + if (!\is_string($str)) { + throw new \InvalidArgumentException('Query and fragment must be a string'); + } + + return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [__CLASS__, 'rawurlencodeMatchZero'], $str); + } + + private static function rawurlencodeMatchZero(array $match) + { + return \rawurlencode($match[0]); + } + +} diff --git a/src/vendor/mpdf/psr-log-aware-trait/README.md b/src/vendor/mpdf/psr-log-aware-trait/README.md new file mode 100644 index 000000000..9545e7728 --- /dev/null +++ b/src/vendor/mpdf/psr-log-aware-trait/README.md @@ -0,0 +1,20 @@ +# psr-log-aware-trait + +Trait to allow support of different psr/log versions. + +By including this PsrLogAwareTrait, you can allow composer to resolve your PsrLogger version for you. + +## Use + +Require the trait. + + composer require chromatic/psr-log-aware-trait + + +In your code, you no longer have to set a $logger property on your classes, since that comes with the trait, and you do not need to implement the `function setLogger()` method, since that also comes along with the trait. + +```php +use PsrLogAwareTrait; +``` + +Will allow you to call `setLogger()` in your classes and fulfil the requirements of the PsrLoggerAwareInterface implementation. diff --git a/src/vendor/mpdf/psr-log-aware-trait/composer.json b/src/vendor/mpdf/psr-log-aware-trait/composer.json new file mode 100644 index 000000000..daf1c388a --- /dev/null +++ b/src/vendor/mpdf/psr-log-aware-trait/composer.json @@ -0,0 +1,24 @@ +{ + "name": "mpdf/psr-log-aware-trait", + "description": "Trait to allow support of different psr/log versions.", + "type": "library", + "require": { + "psr/log": "^1.0 || ^2.0" + }, + "license": "MIT", + "autoload": { + "psr-4": { + "Mpdf\\PsrLogAwareTrait\\": "src/" + } + }, + "authors": [ + { + "name": "Mark Dorison", + "email": "mark@chromatichq.com" + }, + { + "name": "Kristofer Widholm", + "email": "kristofer@chromatichq.com" + } + ] +} diff --git a/src/vendor/mpdf/psr-log-aware-trait/src/MpdfPsrLogAwareTrait.php b/src/vendor/mpdf/psr-log-aware-trait/src/MpdfPsrLogAwareTrait.php new file mode 100644 index 000000000..4900229e1 --- /dev/null +++ b/src/vendor/mpdf/psr-log-aware-trait/src/MpdfPsrLogAwareTrait.php @@ -0,0 +1,27 @@ +logger = $logger; + if (property_exists($this, 'services') && is_array($this->services)) { + foreach ($this->services as $name) { + if ($this->$name && $this->$name instanceof \Psr\Log\LoggerAwareInterface) { + $this->$name->setLogger($logger); + } + } + } + } + +} diff --git a/src/vendor/mpdf/psr-log-aware-trait/src/PsrLogAwareTrait.php b/src/vendor/mpdf/psr-log-aware-trait/src/PsrLogAwareTrait.php new file mode 100644 index 000000000..e2db69c3e --- /dev/null +++ b/src/vendor/mpdf/psr-log-aware-trait/src/PsrLogAwareTrait.php @@ -0,0 +1,20 @@ +logger = $logger; + } + +} diff --git a/src/vendor/myclabs/php-enum/.gitattributes b/src/vendor/myclabs/php-enum/.gitattributes new file mode 100644 index 000000000..50b8b8a9a --- /dev/null +++ b/src/vendor/myclabs/php-enum/.gitattributes @@ -0,0 +1,6 @@ +# Auto detect text files and perform LF normalization +* text=auto + +tests/ export-ignore +phpunit.xml export-ignore +.travis.yml export-ignore diff --git a/src/vendor/myclabs/php-enum/LICENSE b/src/vendor/myclabs/php-enum/LICENSE index 2a8cf22ec..accd5a0f0 100644 --- a/src/vendor/myclabs/php-enum/LICENSE +++ b/src/vendor/myclabs/php-enum/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +php-enum - PHP Enum implementation http://github.com/myclabs/php-enum -Copyright (c) 2015 My C-Labs +Copyright (C) 2015 My C-Labs 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, diff --git a/src/vendor/myclabs/php-enum/README.md b/src/vendor/myclabs/php-enum/README.md index 948f37458..6a08e0ad3 100644 --- a/src/vendor/myclabs/php-enum/README.md +++ b/src/vendor/myclabs/php-enum/README.md @@ -1,20 +1,16 @@ # PHP Enum implementation inspired from SplEnum -[![GitHub Actions][GA Image]][GA Link] +[![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum) [![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) [![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) -[![Psalm Shepherd][Shepherd Image]][Shepherd Link] - -Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). ## Why? -First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. +First, and mainly, `SplEnum` is not integrated to PHP, you have to install it separately. Using an enum instead of class constants provides the following advantages: -- You can use an enum as a parameter type: `function setAction(Action $action) {` -- You can use an enum as a return type: `function getAction() : Action {` +- You can type-hint: `function setAction(Action $action) {` - You can enrich the enum with methods (e.g. `format`, `parse`, …) - You can extend the enum to add new values (make your enum `final` to prevent it) - You can get a list of all the possible values (see below) @@ -34,32 +30,28 @@ use MyCLabs\Enum\Enum; /** * Action enum - * - * @extends Enum */ -final class Action extends Enum +class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; } ``` +Note the `private` keyword requires PHP > 7.1, you can omit it on PHP 7.0. + ## Usage ```php -$action = Action::VIEW(); +$action = new Action(Action::VIEW); -// or with a dynamic key: -$action = Action::$key(); -// or with a dynamic value: -$action = Action::from($value); // or -$action = new Action($value); +$action = Action::VIEW(); ``` As you can see, static methods are automatically implemented to provide quick access to an enum value. -One advantage over using class constants is to be able to use an enum as a parameter type: +One advantage over using class constants is to be able to type-hint enum values: ```php function setAction(Action $action) { @@ -77,19 +69,17 @@ function setAction(Action $action) { Static methods: -- `from()` Creates an Enum instance, checking that the value exist in the enum - `toArray()` method Returns all possible values as an array (constant name in key, constant value in value) - `keys()` Returns the names (keys) of all constants in the Enum class - `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) - `isValid()` Check if tested value is valid on enum set - `isValidKey()` Check if tested key is valid on enum set -- `assertValidValue()` Assert the value is valid on enum set, throwing exception otherwise - `search()` Return key for searched value ### Static methods ```php -final class Action extends Enum +class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; @@ -105,7 +95,7 @@ Static method helpers are implemented using [`__callStatic()`](http://www.php.ne If you care about IDE autocompletion, you can either implement the static methods yourself: ```php -final class Action extends Enum +class Action extends Enum { private const VIEW = 'view'; @@ -125,72 +115,14 @@ or you can use phpdoc (this is supported in PhpStorm for example): * @method static Action VIEW() * @method static Action EDIT() */ -final class Action extends Enum +class Action extends Enum { private const VIEW = 'view'; private const EDIT = 'edit'; } ``` -## Native enums and migration -Native enum arrived to PHP in version 8.1: https://www.php.net/enumerations -If your project is running PHP 8.1+ or your library has it as a minimum requirement you should use it instead of this library. - -When migrating from `myclabs/php-enum`, the effort should be small if the usage was in the recommended way: -- private constants -- final classes -- no method overridden - -Changes for migration: -- Class definition should be changed from -```php -/** - * @method static Action VIEW() - * @method static Action EDIT() - */ -final class Action extends Enum -{ - private const VIEW = 'view'; - private const EDIT = 'edit'; -} -``` - to -```php -enum Action: string -{ - case VIEW = 'view'; - case EDIT = 'edit'; -} -``` -All places where the class was used as a type will continue to work. - -Usages and the change needed: - -| Operation | myclabs/php-enum | native enum | -|----------------------------------------------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Obtain an instance will change from | `$enumCase = Action::VIEW()` | `$enumCase = Action::VIEW` | -| Create an enum from a backed value | `$enumCase = new Action('view')` | `$enumCase = Action::from('view')` | -| Get the backed value of the enum instance | `$enumCase->getValue()` | `$enumCase->value` | -| Compare two enum instances | `$enumCase1 == $enumCase2`
or
`$enumCase1->equals($enumCase2)` | `$enumCase1 === $enumCase2` | -| Get the key/name of the enum instance | `$enumCase->getKey()` | `$enumCase->name` | -| Get a list of all the possible instances of the enum | `Action::values()` | `Action::cases()` | -| Get a map of possible instances of the enum mapped by name | `Action::values()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), Action::cases())`
or
`(new ReflectionEnum(Action::class))->getConstants()` | -| Get a list of all possible names of the enum | `Action::keys()` | `array_map(fn($case) => $case->name, Action::cases())` | -| Get a list of all possible backed values of the enum | `Action::toArray()` | `array_map(fn($case) => $case->value, Action::cases())` | -| Get a map of possible backed values of the enum mapped by name | `Action::toArray()` | `array_combine(array_map(fn($case) => $case->name, Action::cases()), array_map(fn($case) => $case->value, Action::cases()))`
or
`array_map(fn($case) => $case->value, (new ReflectionEnum(Action::class))->getConstants()))` | - ## Related projects -- [PHP 8.1+ native enum](https://www.php.net/enumerations) - [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) -- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) -- [PHPStan integration](https://github.com/timeweb/phpstan-enum) - - -[GA Image]: https://github.com/myclabs/php-enum/workflows/CI/badge.svg - -[GA Link]: https://github.com/myclabs/php-enum/actions?query=workflow%3A%22CI%22+branch%3Amaster - -[Shepherd Image]: https://shepherd.dev/github/myclabs/php-enum/coverage.svg - -[Shepherd Link]: https://shepherd.dev/github/myclabs/php-enum +- [Symfony 2/3 ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) diff --git a/src/vendor/myclabs/php-enum/composer.json b/src/vendor/myclabs/php-enum/composer.json index eab626353..88bbe16bd 100644 --- a/src/vendor/myclabs/php-enum/composer.json +++ b/src/vendor/myclabs/php-enum/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "PHP Enum implementation", "keywords": ["enum"], - "homepage": "https://github.com/myclabs/php-enum", + "homepage": "http://github.com/myclabs/php-enum", "license": "MIT", "authors": [ { @@ -14,10 +14,7 @@ "autoload": { "psr-4": { "MyCLabs\\Enum\\": "src/" - }, - "classmap": [ - "stubs/Stringable.php" - ] + } }, "autoload-dev": { "psr-4": { @@ -25,12 +22,11 @@ } }, "require": { - "php": "^7.3 || ^8.0", + "php": ">=5.4", "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^4.6.2 || ^5.2" + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "squizlabs/php_codesniffer": "1.*" } } diff --git a/src/vendor/myclabs/php-enum/src/Enum.php b/src/vendor/myclabs/php-enum/src/Enum.php index 1bd559213..aa36c4286 100644 --- a/src/vendor/myclabs/php-enum/src/Enum.php +++ b/src/vendor/myclabs/php-enum/src/Enum.php @@ -14,99 +14,47 @@ namespace MyCLabs\Enum; * @author Matthieu Napoli * @author Daniel Costa * @author Mirosław Filip - * - * @psalm-template T - * @psalm-immutable - * @psalm-consistent-constructor */ -abstract class Enum implements \JsonSerializable, \Stringable +abstract class Enum implements \JsonSerializable { /** * Enum value * * @var mixed - * @psalm-var T */ protected $value; - /** - * Enum key, the constant name - * - * @var string - */ - private $key; - /** * Store existing constants in a static cache per object. * - * * @var array - * @psalm-var array> */ protected static $cache = []; - /** - * Cache of instances of the Enum class - * - * @var array - * @psalm-var array> - */ - protected static $instances = []; - /** * Creates a new value of some type * - * @psalm-pure * @param mixed $value * - * @psalm-param T $value * @throws \UnexpectedValueException if incompatible type is given. */ public function __construct($value) { if ($value instanceof static) { - /** @psalm-var T */ - $value = $value->getValue(); + $this->value = $value->getValue(); + + return; } - /** @psalm-suppress ImplicitToStringCast assertValidValueReturningKey returns always a string but psalm has currently an issue here */ - $this->key = static::assertValidValueReturningKey($value); + if (!$this->isValid($value)) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . \get_called_class()); + } - /** @psalm-var T */ $this->value = $value; } /** - * This method exists only for the compatibility reason when deserializing a previously serialized version - * that didn't had the key property - */ - public function __wakeup() - { - /** @psalm-suppress DocblockTypeContradiction key can be null when deserializing an enum without the key */ - if ($this->key === null) { - /** - * @psalm-suppress InaccessibleProperty key is not readonly as marked by psalm - * @psalm-suppress PossiblyFalsePropertyAssignmentValue deserializing a case that was removed - */ - $this->key = static::search($this->value); - } - } - - /** - * @param mixed $value - * @return static - */ - public static function from($value): self - { - $key = static::assertValidValueReturningKey($value); - - return self::__callStatic($key, []); - } - - /** - * @psalm-pure * @return mixed - * @psalm-return T */ public function getValue() { @@ -116,17 +64,14 @@ abstract class Enum implements \JsonSerializable, \Stringable /** * Returns the enum key (i.e. the constant name). * - * @psalm-pure - * @return string + * @return mixed */ public function getKey() { - return $this->key; + return static::search($this->value); } /** - * @psalm-pure - * @psalm-suppress InvalidCast * @return string */ public function __toString() @@ -135,27 +80,20 @@ abstract class Enum implements \JsonSerializable, \Stringable } /** - * Determines if Enum should be considered equal with the variable passed as a parameter. - * Returns false if an argument is an object of different class or not an object. + * Compares one Enum with another. * * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 * - * @psalm-pure - * @psalm-param mixed $variable - * @return bool + * @return bool True if Enums are equal, false if not equal */ - final public function equals($variable = null): bool + final public function equals(Enum $enum = null) { - return $variable instanceof self - && $this->getValue() === $variable->getValue() - && static::class === \get_class($variable); + return $enum !== null && $this->getValue() === $enum->getValue() && \get_called_class() === \get_class($enum); } /** * Returns the names (keys) of all constants in the Enum class * - * @psalm-pure - * @psalm-return list * @return array */ public static function keys() @@ -166,17 +104,13 @@ abstract class Enum implements \JsonSerializable, \Stringable /** * Returns instances of the Enum class of all Enum constants * - * @psalm-pure - * @psalm-return array * @return static[] Constant name in key, Enum instance in value */ public static function values() { $values = array(); - /** @psalm-var T $value */ foreach (static::toArray() as $key => $value) { - /** @psalm-suppress UnsafeGenericInstantiation */ $values[$key] = new static($value); } @@ -186,20 +120,13 @@ abstract class Enum implements \JsonSerializable, \Stringable /** * Returns all possible values as an array * - * @psalm-pure - * @psalm-suppress ImpureStaticProperty - * - * @psalm-return array * @return array Constant name in key, constant value in value */ public static function toArray() { - $class = static::class; - + $class = \get_called_class(); if (!isset(static::$cache[$class])) { - /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ $reflection = new \ReflectionClass($class); - /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ static::$cache[$class] = $reflection->getConstants(); } @@ -210,9 +137,7 @@ abstract class Enum implements \JsonSerializable, \Stringable * Check if is valid enum value * * @param $value - * @psalm-param mixed $value - * @psalm-pure - * @psalm-assert-if-true T $value + * * @return bool */ public static function isValid($value) @@ -220,41 +145,11 @@ abstract class Enum implements \JsonSerializable, \Stringable return \in_array($value, static::toArray(), true); } - /** - * Asserts valid enum value - * - * @psalm-pure - * @psalm-assert T $value - * @param mixed $value - */ - public static function assertValidValue($value): void - { - self::assertValidValueReturningKey($value); - } - - /** - * Asserts valid enum value - * - * @psalm-pure - * @psalm-assert T $value - * @param mixed $value - * @return string - */ - private static function assertValidValueReturningKey($value): string - { - if (false === ($key = static::search($value))) { - throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); - } - - return $key; - } - /** * Check if is valid enum key * * @param $key - * @psalm-param string $key - * @psalm-pure + * * @return bool */ public static function isValidKey($key) @@ -267,11 +162,9 @@ abstract class Enum implements \JsonSerializable, \Stringable /** * Return key for value * - * @param mixed $value + * @param $value * - * @psalm-param mixed $value - * @psalm-pure - * @return string|false + * @return mixed */ public static function search($value) { @@ -286,22 +179,15 @@ abstract class Enum implements \JsonSerializable, \Stringable * * @return static * @throws \BadMethodCallException - * - * @psalm-pure */ public static function __callStatic($name, $arguments) { - $class = static::class; - if (!isset(self::$instances[$class][$name])) { - $array = static::toArray(); - if (!isset($array[$name]) && !\array_key_exists($name, $array)) { - $message = "No static method or enum constant '$name' in class " . static::class; - throw new \BadMethodCallException($message); - } - /** @psalm-suppress UnsafeGenericInstantiation */ - return self::$instances[$class][$name] = new static($array[$name]); + $array = static::toArray(); + if (isset($array[$name]) || \array_key_exists($name, $array)) { + return new static($array[$name]); } - return clone self::$instances[$class][$name]; + + throw new \BadMethodCallException("No static method or enum constant '$name' in class " . \get_called_class()); } /** @@ -311,7 +197,6 @@ abstract class Enum implements \JsonSerializable, \Stringable * @return mixed * @link http://php.net/manual/en/jsonserializable.jsonserialize.php */ - #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->getValue(); diff --git a/src/vendor/overtrue/socialite/src/Providers/AbstractProvider.php b/src/vendor/overtrue/socialite/src/Providers/AbstractProvider.php index b33e6dac9..a31c507fb 100644 --- a/src/vendor/overtrue/socialite/src/Providers/AbstractProvider.php +++ b/src/vendor/overtrue/socialite/src/Providers/AbstractProvider.php @@ -213,6 +213,23 @@ abstract class AbstractProvider implements ProviderInterface return $user->setToken($token)->setProviderName($this->getName()); } + /** + * @param $code + */ + public function userByCode($code, AccessTokenInterface $token = null){ + if (is_null($token) && $this->hasInvalidState()) { + throw new InvalidStateException(); + } + + $token = $token ?: $this->getAccessToken($code); + + $user = $this->getUserByToken($token); + + $user = $this->mapUserToObject($user)->merge(['original' => $user]); + + return $user->setToken($token)->setProviderName($this->getName()); + } + /** * Set redirect url. * diff --git a/src/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php b/src/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php index 7efde33a3..9e78f38bc 100644 --- a/src/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php +++ b/src/vendor/overtrue/socialite/src/Providers/WeWorkProvider.php @@ -160,6 +160,7 @@ class WeWorkProvider extends AbstractProvider implements ProviderInterface 'query' => array_filter([ 'access_token' => $token->getToken(), 'code' => $this->getCode(), + 'debug' => 1 ]), ]); diff --git a/src/vendor/overtrue/wechat/composer.json b/src/vendor/overtrue/wechat/composer.json index ad21285bd..13f835718 100644 --- a/src/vendor/overtrue/wechat/composer.json +++ b/src/vendor/overtrue/wechat/composer.json @@ -1,62 +1,60 @@ { - "name": "overtrue/wechat", - "description": "微信SDK", - "keywords": [ - "easywechat", - "wechat", - "weixin", - "weixin-sdk", - "sdk" - ], - "license": "MIT", - "authors": [ - { - "name": "overtrue", - "email": "anzhengchao@gmail.com" - } - ], - "require": { - "php": ">=7.2", - "ext-fileinfo": "*", - "ext-openssl": "*", - "ext-simplexml": "*", - "easywechat-composer/easywechat-composer": "^1.1", - "guzzlehttp/guzzle": "^6.2 || ^7.0", - "monolog/monolog": "^1.22 || ^2.0", - "overtrue/socialite": "~2.0", - "pimple/pimple": "^3.0", - "psr/simple-cache": "^1.0", - "symfony/cache": "^3.3 || ^4.3 || ^5.0", - "symfony/event-dispatcher": "^4.3 || ^5.0", - "symfony/http-foundation": "^2.7 || ^3.0 || ^4.0 || ^5.0", - "symfony/psr-http-message-bridge": "^0.3 || ^1.0 || ^2.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.15", - "mikey179/vfsstream": "^1.6", - "mockery/mockery": "^1.2.3", - "phpstan/phpstan": "^0.12.0", - "phpunit/phpunit": "^7.5" - }, - "autoload": { - "psr-4": { - "EasyWeChat\\": "src/" + "name": "overtrue/wechat", + "description": "微信SDK", + "keywords": [ + "easywechat", + "wechat", + "weixin", + "weixin-sdk", + "sdk" + ], + "license": "MIT", + "authors": [ + { + "name": "overtrue", + "email": "anzhengchao@gmail.com" + } + ], + "require": { + "php": ">=7.2", + "ext-fileinfo": "*", + "ext-openssl": "*", + "ext-simplexml": "*", + "easywechat-composer/easywechat-composer": "^1.1", + "guzzlehttp/guzzle": "^6.2", + "monolog/monolog": "^1.22 || ^2.0", + "overtrue/socialite": "~2.0", + "pimple/pimple": "^3.0", + "psr/simple-cache": "^1.0", + "symfony/cache": "^3.3 || ^4.3 || ^5.0", + "symfony/event-dispatcher": "^4.3 || ^5.0", + "symfony/http-foundation": "^2.7 || ^3.0 || ^4.0 || ^5.0", + "symfony/psr-http-message-bridge": "^0.3 || ^1.0" }, - "files": [ - "src/Kernel/Support/Helpers.php", - "src/Kernel/Helpers.php" - ] - }, - "autoload-dev": { - "psr-4": { - "EasyWeChat\\Tests\\": "tests/" + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.15", + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.2.3", + "phpstan/phpstan": "^0.12.0", + "phpunit/phpunit": "^7.5" + }, + "autoload": { + "psr-4": { + "EasyWeChat\\": "src/" + }, + "files": [ + "src/Kernel/Support/Helpers.php", + "src/Kernel/Helpers.php" + ] + }, + "autoload-dev": { + "psr-4": { + "EasyWeChat\\Tests\\": "tests/" + } + }, + "scripts": { + "phpcs": "vendor/bin/php-cs-fixer fix", + "phpstan": "vendor/bin/phpstan analyse", + "test": "vendor/bin/phpunit" } - }, - "scripts": { - "phpcs": "vendor/bin/php-cs-fixer fix", - "phpstan": "vendor/bin/phpstan analyse", - "check-style": "php-cs-fixer fix --using-cache=no --diff --config=.php_cs --dry-run --ansi", - "fix-style": "php-cs-fixer fix --using-cache=no --config=.php_cs --ansi", - "test": "vendor/bin/phpunit --colors=always" - } } diff --git a/src/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php b/src/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php index 227d041df..7bc11bdb0 100644 --- a/src/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php +++ b/src/vendor/overtrue/wechat/src/BasicService/ContentSecurity/Client.php @@ -29,6 +29,8 @@ class Client extends BaseClient /** * Text content security check. * + * @param string $text + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -46,6 +48,8 @@ class Client extends BaseClient /** * Image security check. * + * @param string $path + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +63,9 @@ class Client extends BaseClient /** * Media security check. * + * @param string $mediaUrl + * @param int $mediaType + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -87,6 +94,8 @@ class Client extends BaseClient /** * Image security check async. * + * @param string $mediaUrl + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -100,6 +109,8 @@ class Client extends BaseClient /** * Audio security check async. * + * @param string $mediaUrl + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php b/src/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php index 565e2995d..33367fc2d 100644 --- a/src/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php +++ b/src/vendor/overtrue/wechat/src/BasicService/Jssdk/Client.php @@ -40,23 +40,20 @@ class Client extends BaseClient /** * Get config json for jsapi. * - * @param array $jsApiList - * @param bool $debug - * @param bool $beta - * @param bool $json - * @param array $openTagList - * @param string $url + * @param array $jsApiList + * @param bool $debug + * @param bool $beta + * @param bool $json * * @return array|string * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ - public function buildConfig(array $jsApiList, bool $debug = false, bool $beta = false, bool $json = true, array $openTagList = [], string $url = null) + public function buildConfig(array $jsApiList, bool $debug = false, bool $beta = false, bool $json = true) { - $config = array_merge(compact('debug', 'beta', 'jsApiList', 'openTagList'), $this->configSignature($url)); + $config = array_merge(compact('debug', 'beta', 'jsApiList'), $this->configSignature()); return $json ? json_encode($config) : $config; } @@ -64,27 +61,29 @@ class Client extends BaseClient /** * Return jsapi config as a PHP array. * - * @param array $apis - * @param bool $debug - * @param bool $beta - * @param array $openTagList - * @param string $url + * @param array $apis + * @param bool $debug + * @param bool $beta * * @return array * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ - public function getConfigArray(array $apis, bool $debug = false, bool $beta = false, array $openTagList = [], string $url = null) + public function getConfigArray(array $apis, bool $debug = false, bool $beta = false) { - return $this->buildConfig($apis, $debug, $beta, false, $openTagList, $url); + return $this->buildConfig($apis, $debug, $beta, false); } /** * Get js ticket. * + * @param bool $refresh + * @param string $type + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException @@ -117,7 +116,11 @@ class Client extends BaseClient /** * Build signature. * - * @param int|null $timestamp + * @param string|null $url + * @param string|null $nonce + * @param int|null $timestamp + * + * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -146,6 +149,8 @@ class Client extends BaseClient * @param string $nonce * @param int $timestamp * @param string $url + * + * @return string */ public function getTicketSignature($ticket, $nonce, $timestamp, $url): string { @@ -167,6 +172,8 @@ class Client extends BaseClient /** * Set current url. * + * @param string $url + * * @return $this */ public function setUrl(string $url) @@ -178,6 +185,8 @@ class Client extends BaseClient /** * Get current url. + * + * @return string */ public function getUrl(): string { diff --git a/src/vendor/overtrue/wechat/src/BasicService/Media/Client.php b/src/vendor/overtrue/wechat/src/BasicService/Media/Client.php index 21c0dfd99..13f1afa87 100644 --- a/src/vendor/overtrue/wechat/src/BasicService/Media/Client.php +++ b/src/vendor/overtrue/wechat/src/BasicService/Media/Client.php @@ -97,6 +97,9 @@ class Client extends BaseClient /** * Upload temporary material. * + * @param string $type + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -117,6 +120,10 @@ class Client extends BaseClient } /** + * @param string $path + * @param string $title + * @param string $description + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -137,6 +144,10 @@ class Client extends BaseClient } /** + * @param string $mediaId + * @param string $title + * @param string $description + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -154,6 +165,8 @@ class Client extends BaseClient /** * Fetch item from WeChat server. * + * @param string $mediaId + * * @return \EasyWeChat\Kernel\Http\StreamResponse|\Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -175,6 +188,8 @@ class Client extends BaseClient } /** + * @param string $mediaId + * * @return array|\EasyWeChat\Kernel\Http\Response|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php b/src/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php index 15a8f6404..ac606a396 100644 --- a/src/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php +++ b/src/vendor/overtrue/wechat/src/BasicService/QrCode/Client.php @@ -25,13 +25,13 @@ class Client extends BaseClient */ protected $baseUri = 'https://api.weixin.qq.com/cgi-bin/'; - public const DAY = 86400; - public const SCENE_MAX_VALUE = 100000; - public const SCENE_QR_CARD = 'QR_CARD'; - public const SCENE_QR_TEMPORARY = 'QR_SCENE'; - public const SCENE_QR_TEMPORARY_STR = 'QR_STR_SCENE'; - public const SCENE_QR_FOREVER = 'QR_LIMIT_SCENE'; - public const SCENE_QR_FOREVER_STR = 'QR_LIMIT_STR_SCENE'; + const DAY = 86400; + const SCENE_MAX_VALUE = 100000; + const SCENE_QR_CARD = 'QR_CARD'; + const SCENE_QR_TEMPORARY = 'QR_SCENE'; + const SCENE_QR_TEMPORARY_STR = 'QR_STR_SCENE'; + const SCENE_QR_FOREVER = 'QR_LIMIT_SCENE'; + const SCENE_QR_FOREVER_STR = 'QR_LIMIT_STR_SCENE'; /** * Create forever QR code. diff --git a/src/vendor/overtrue/wechat/src/BasicService/Url/Client.php b/src/vendor/overtrue/wechat/src/BasicService/Url/Client.php index bac5c4072..19a5fb10d 100644 --- a/src/vendor/overtrue/wechat/src/BasicService/Url/Client.php +++ b/src/vendor/overtrue/wechat/src/BasicService/Url/Client.php @@ -28,6 +28,8 @@ class Client extends BaseClient /** * Shorten the url. * + * @param string $url + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Factory.php b/src/vendor/overtrue/wechat/src/Factory.php index a004b0587..295b4ffc6 100644 --- a/src/vendor/overtrue/wechat/src/Factory.php +++ b/src/vendor/overtrue/wechat/src/Factory.php @@ -27,6 +27,7 @@ class Factory { /** * @param string $name + * @param array $config * * @return \EasyWeChat\Kernel\ServiceContainer */ diff --git a/src/vendor/overtrue/wechat/src/Kernel/AccessToken.php b/src/vendor/overtrue/wechat/src/Kernel/AccessToken.php index bdb21904e..e7ae696a1 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/Kernel/AccessToken.php @@ -76,6 +76,8 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -88,6 +90,10 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @param bool $refresh + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -99,8 +105,8 @@ abstract class AccessToken implements AccessTokenInterface $cacheKey = $this->getCacheKey(); $cache = $this->getCache(); - if (!$refresh && $cache->has($cacheKey) && $result = $cache->get($cacheKey)) { - return $result; + if (!$refresh && $cache->has($cacheKey)) { + return $cache->get($cacheKey); } /** @var array $token */ @@ -114,6 +120,11 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @param string $token + * @param int $lifetime + * + * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException * @throws \Psr\SimpleCache\InvalidArgumentException @@ -133,6 +144,8 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @return \EasyWeChat\Kernel\Contracts\AccessTokenInterface + * * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -147,7 +160,8 @@ abstract class AccessToken implements AccessTokenInterface } /** - * @param bool $toArray + * @param array $credentials + * @param bool $toArray * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -169,6 +183,11 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @param \Psr\Http\Message\RequestInterface $request + * @param array $requestOptions + * + * @return \Psr\Http\Message\RequestInterface + * * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -187,6 +206,10 @@ abstract class AccessToken implements AccessTokenInterface /** * Send http request. * + * @param array $credentials + * + * @return ResponseInterface + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \GuzzleHttp\Exception\GuzzleException */ @@ -210,6 +233,8 @@ abstract class AccessToken implements AccessTokenInterface /** * The request query will be used to add to the request. * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -222,6 +247,8 @@ abstract class AccessToken implements AccessTokenInterface } /** + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ public function getEndpoint(): string @@ -243,6 +270,8 @@ abstract class AccessToken implements AccessTokenInterface /** * Credential for get token. + * + * @return array */ abstract protected function getCredentials(): array; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/BaseClient.php b/src/vendor/overtrue/wechat/src/Kernel/BaseClient.php index 389a0f962..45c9951bc 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/BaseClient.php +++ b/src/vendor/overtrue/wechat/src/Kernel/BaseClient.php @@ -47,7 +47,8 @@ class BaseClient /** * BaseClient constructor. * - * @param \EasyWeChat\Kernel\ServiceContainer $app + * @param \EasyWeChat\Kernel\ServiceContainer $app + * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface|null $accessToken */ public function __construct(ServiceContainer $app, AccessTokenInterface $accessToken = null) { @@ -58,6 +59,9 @@ class BaseClient /** * GET request. * + * @param string $url + * @param array $query + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -71,6 +75,9 @@ class BaseClient /** * POST request. * + * @param string $url + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -84,6 +91,10 @@ class BaseClient /** * JSON request. * + * @param string $url + * @param array $data + * @param array $query + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -97,6 +108,11 @@ class BaseClient /** * Upload file. * + * @param string $url + * @param array $files + * @param array $form + * @param array $query + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -120,12 +136,17 @@ class BaseClient return $this->request($url, 'POST', ['query' => $query, 'multipart' => $multipart, 'connect_timeout' => 30, 'timeout' => 30, 'read_timeout' => 30]); } + /** + * @return AccessTokenInterface + */ public function getAccessToken(): AccessTokenInterface { return $this->accessToken; } /** + * @param \EasyWeChat\Kernel\Contracts\AccessTokenInterface $accessToken + * * @return $this */ public function setAccessToken(AccessTokenInterface $accessToken) @@ -136,7 +157,10 @@ class BaseClient } /** - * @param bool $returnRaw + * @param string $url + * @param string $method + * @param array $options + * @param bool $returnRaw * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -148,7 +172,6 @@ class BaseClient if (empty($this->middlewares)) { $this->registerHttpMiddlewares(); } - $response = $this->performRequest($url, $method, $options); $this->app->events->dispatch(new Events\HttpResponseCreated($response)); @@ -157,6 +180,10 @@ class BaseClient } /** + * @param string $url + * @param string $method + * @param array $options + * * @return \EasyWeChat\Kernel\Http\Response * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -192,7 +219,6 @@ class BaseClient if ($this->accessToken) { $request = $this->accessToken->applyToRequest($request, $options); } - return $handler($request, $options); }; }; diff --git a/src/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php b/src/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php index 69268ffa3..56f4a4d1e 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Contracts/AccessTokenInterface.php @@ -20,6 +20,9 @@ use Psr\Http\Message\RequestInterface; */ interface AccessTokenInterface { + /** + * @return array + */ public function getToken(): array; /** @@ -27,5 +30,11 @@ interface AccessTokenInterface */ public function refresh(): self; + /** + * @param \Psr\Http\Message\RequestInterface $request + * @param array $requestOptions + * + * @return \Psr\Http\Message\RequestInterface + */ public function applyToRequest(RequestInterface $request, array $requestOptions = []): RequestInterface; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php b/src/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php index a8ded096a..63768cff8 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Contracts/MediaInterface.php @@ -18,5 +18,8 @@ namespace EasyWeChat\Kernel\Contracts; */ interface MediaInterface extends MessageInterface { + /** + * @return string + */ public function getMediaId(): string; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php b/src/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php index 32aec4a14..29ddb57b9 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Contracts/MessageInterface.php @@ -18,9 +18,18 @@ namespace EasyWeChat\Kernel\Contracts; */ interface MessageInterface { + /** + * @return string + */ public function getType(): string; + /** + * @return array + */ public function transformForJsonRequest(): array; + /** + * @return string + */ public function transformToXml(): string; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Encryptor.php b/src/vendor/overtrue/wechat/src/Kernel/Encryptor.php index bebb2a562..150ad216d 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Encryptor.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Encryptor.php @@ -13,9 +13,9 @@ namespace EasyWeChat\Kernel; use EasyWeChat\Kernel\Exceptions\RuntimeException; use EasyWeChat\Kernel\Support\AES; +use function EasyWeChat\Kernel\Support\str_random; use EasyWeChat\Kernel\Support\XML; use Throwable; -use function EasyWeChat\Kernel\Support\str_random; /** * Class Encryptor. @@ -24,18 +24,18 @@ use function EasyWeChat\Kernel\Support\str_random; */ class Encryptor { - public const ERROR_INVALID_SIGNATURE = -40001; // Signature verification failed - public const ERROR_PARSE_XML = -40002; // Parse XML failed - public const ERROR_CALC_SIGNATURE = -40003; // Calculating the signature failed - public const ERROR_INVALID_AES_KEY = -40004; // Invalid AESKey - public const ERROR_INVALID_APP_ID = -40005; // Check AppID failed - public const ERROR_ENCRYPT_AES = -40006; // AES EncryptionInterface failed - public const ERROR_DECRYPT_AES = -40007; // AES decryption failed - public const ERROR_INVALID_XML = -40008; // Invalid XML - public const ERROR_BASE64_ENCODE = -40009; // Base64 encoding failed - public const ERROR_BASE64_DECODE = -40010; // Base64 decoding failed - public const ERROR_XML_BUILD = -40011; // XML build failed - public const ILLEGAL_BUFFER = -41003; // Illegal buffer + const ERROR_INVALID_SIGNATURE = -40001; // Signature verification failed + const ERROR_PARSE_XML = -40002; // Parse XML failed + const ERROR_CALC_SIGNATURE = -40003; // Calculating the signature failed + const ERROR_INVALID_AES_KEY = -40004; // Invalid AESKey + const ERROR_INVALID_APP_ID = -40005; // Check AppID failed + const ERROR_ENCRYPT_AES = -40006; // AES EncryptionInterface failed + const ERROR_DECRYPT_AES = -40007; // AES decryption failed + const ERROR_INVALID_XML = -40008; // Invalid XML + const ERROR_BASE64_ENCODE = -40009; // Base64 encoding failed + const ERROR_BASE64_DECODE = -40010; // Base64 decoding failed + const ERROR_XML_BUILD = -40011; // XML build failed + const ILLEGAL_BUFFER = -41003; // Illegal buffer /** * App id. @@ -65,6 +65,10 @@ class Encryptor /** * Constructor. + * + * @param string $appId + * @param string|null $token + * @param string|null $aesKey */ public function __construct(string $appId, string $token = null, string $aesKey = null) { @@ -75,6 +79,8 @@ class Encryptor /** * Get the app token. + * + * @return string */ public function getToken(): string { @@ -88,6 +94,8 @@ class Encryptor * @param string $nonce * @param int $timestamp * + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function encrypt($xml, $nonce = null, $timestamp = null): string @@ -129,6 +137,8 @@ class Encryptor * @param string $nonce * @param string $timestamp * + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function decrypt($content, $msgSignature, $nonce, $timestamp): string @@ -158,6 +168,8 @@ class Encryptor /** * Get SHA1. + * + * @return string */ public function signature(): string { @@ -170,6 +182,11 @@ class Encryptor /** * PKCS#7 pad. * + * @param string $text + * @param int $blockSize + * + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function pkcs7Pad(string $text, int $blockSize): string @@ -185,6 +202,10 @@ class Encryptor /** * PKCS#7 unpad. + * + * @param string $text + * + * @return string */ public function pkcs7Unpad(string $text): string { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php b/src/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php index 6fd0aca5a..a82990126 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Events/AccessTokenRefreshed.php @@ -25,6 +25,9 @@ class AccessTokenRefreshed */ public $accessToken; + /** + * @param \EasyWeChat\Kernel\AccessToken $accessToken + */ public function __construct(AccessToken $accessToken) { $this->accessToken = $accessToken; diff --git a/src/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php b/src/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php index c83df65af..89d67febc 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Events/ApplicationInitialized.php @@ -25,6 +25,9 @@ class ApplicationInitialized */ public $app; + /** + * @param \EasyWeChat\Kernel\ServiceContainer $app + */ public function __construct(ServiceContainer $app) { $this->app = $app; diff --git a/src/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php b/src/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php index 809de20b3..225726076 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Events/HttpResponseCreated.php @@ -25,6 +25,9 @@ class HttpResponseCreated */ public $response; + /** + * @param \Psr\Http\Message\ResponseInterface $response + */ public function __construct(ResponseInterface $response) { $this->response = $response; diff --git a/src/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php b/src/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php index 46e221d14..3ab9925bd 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Events/ServerGuardResponseCreated.php @@ -25,6 +25,9 @@ class ServerGuardResponseCreated */ public $response; + /** + * @param \Symfony\Component\HttpFoundation\Response $response + */ public function __construct(Response $response) { $this->response = $response; diff --git a/src/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php b/src/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php index 5f64064f0..8ab130d1f 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Exceptions/HttpException.php @@ -33,9 +33,10 @@ class HttpException extends Exception /** * HttpException constructor. * - * @param string $message - * @param null $formattedResponse - * @param int|null $code + * @param string $message + * @param \Psr\Http\Message\ResponseInterface|null $response + * @param null $formattedResponse + * @param int|null $code */ public function __construct($message, ResponseInterface $response = null, $formattedResponse = null, $code = null) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Http/Response.php b/src/vendor/overtrue/wechat/src/Kernel/Http/Response.php index 4ff2f7624..adcd4163b 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Http/Response.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Http/Response.php @@ -36,6 +36,8 @@ class Response extends GuzzleResponse } /** + * @param \Psr\Http\Message\ResponseInterface $response + * * @return \EasyWeChat\Kernel\Http\Response */ public static function buildFromPsrResponse(ResponseInterface $response) @@ -108,6 +110,8 @@ class Response extends GuzzleResponse } /** + * @param string $content + * * @return string */ protected function removeControlCharacters(string $content) diff --git a/src/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php b/src/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php index 91c1346d7..104e8c386 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Http/StreamResponse.php @@ -23,6 +23,10 @@ use EasyWeChat\Kernel\Support\File; class StreamResponse extends Response { /** + * @param string $directory + * @param string $filename + * @param bool $appendSuffix + * * @return bool|int * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -66,6 +70,10 @@ class StreamResponse extends Response } /** + * @param string $directory + * @param string $filename + * @param bool $appendSuffix + * * @return bool|int * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Kernel/Log/LogManager.php b/src/vendor/overtrue/wechat/src/Kernel/Log/LogManager.php index 0d46e48cd..915946441 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Log/LogManager.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Log/LogManager.php @@ -17,7 +17,6 @@ use Monolog\Formatter\LineFormatter; use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\FormattableHandlerInterface; use Monolog\Handler\HandlerInterface; -use Monolog\Handler\NullHandler; use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\SlackWebhookHandler; use Monolog\Handler\StreamHandler; @@ -70,6 +69,8 @@ class LogManager implements LoggerInterface /** * LogManager constructor. + * + * @param \EasyWeChat\Kernel\ServiceContainer $app */ public function __construct(ServiceContainer $app) { @@ -79,8 +80,8 @@ class LogManager implements LoggerInterface /** * Create a new, on-demand aggregate logger instance. * - * @param array $channels - * @param string|null $channel + * @param array $channels + * @param string|null $channel * * @return \Psr\Log\LoggerInterface * @@ -173,16 +174,6 @@ class LogManager implements LoggerInterface throw new InvalidArgumentException(\sprintf('Driver [%s] is not supported.', $config['driver'])); } - /** - * Call a custom driver creator. - * - * @return mixed - */ - protected function callCustomCreator(array $config) - { - return $this->customCreators[$config['driver']]($this->app, $config); - } - /** * Create an emergency log handler to avoid white screens of death. * @@ -198,9 +189,23 @@ class LogManager implements LoggerInterface )])); } + /** + * Call a custom driver creator. + * + * @param array $config + * + * @return mixed + */ + protected function callCustomCreator(array $config) + { + return $this->customCreators[$config['driver']]($this->app, $config); + } + /** * Create an aggregate log driver instance. * + * @param array $config + * * @return \Monolog\Logger * * @throws \Exception @@ -223,6 +228,8 @@ class LogManager implements LoggerInterface /** * Create an instance of the single file log driver. * + * @param array $config + * * @return \Psr\Log\LoggerInterface * * @throws \Exception @@ -243,6 +250,8 @@ class LogManager implements LoggerInterface /** * Create an instance of the daily file log driver. * + * @param array $config + * * @return \Psr\Log\LoggerInterface */ protected function createDailyDriver(array $config) @@ -262,6 +271,8 @@ class LogManager implements LoggerInterface /** * Create an instance of the Slack log driver. * + * @param array $config + * * @return \Psr\Log\LoggerInterface */ protected function createSlackDriver(array $config) @@ -285,6 +296,8 @@ class LogManager implements LoggerInterface /** * Create an instance of the syslog log driver. * + * @param array $config + * * @return \Psr\Log\LoggerInterface */ protected function createSyslogDriver(array $config) @@ -301,6 +314,8 @@ class LogManager implements LoggerInterface /** * Create an instance of the "error log" log driver. * + * @param array $config + * * @return \Psr\Log\LoggerInterface */ protected function createErrorlogDriver(array $config) @@ -315,14 +330,11 @@ class LogManager implements LoggerInterface ]); } - protected function createNullDriver() - { - return new Monolog('EasyWeChat', [new NullHandler()]); - } - /** * Prepare the handlers for usage by Monolog. * + * @param array $handlers + * * @return array */ protected function prepareHandlers(array $handlers) @@ -337,6 +349,8 @@ class LogManager implements LoggerInterface /** * Prepare the handler for usage by Monolog. * + * @param \Monolog\Handler\HandlerInterface $handler + * * @return \Monolog\Handler\HandlerInterface */ protected function prepareHandler(HandlerInterface $handler, array $config = []) @@ -366,6 +380,8 @@ class LogManager implements LoggerInterface /** * Extract the log channel from the given configuration. * + * @param array $config + * * @return string */ protected function parseChannel(array $config) @@ -376,6 +392,8 @@ class LogManager implements LoggerInterface /** * Parse the string level into a Monolog constant. * + * @param array $config + * * @return int * * @throws InvalidArgumentException @@ -414,7 +432,8 @@ class LogManager implements LoggerInterface /** * Register a custom driver creator Closure. * - * @param string $driver + * @param string $driver + * @param \Closure $callback * * @return $this */ @@ -429,6 +448,7 @@ class LogManager implements LoggerInterface * System is unusable. * * @param string $message + * @param array $context * * @return mixed * @@ -446,6 +466,7 @@ class LogManager implements LoggerInterface * trigger the SMS alerts and wake you up. * * @param string $message + * @param array $context * * @return mixed * @@ -462,6 +483,7 @@ class LogManager implements LoggerInterface * Example: Application component unavailable, unexpected exception. * * @param string $message + * @param array $context * * @return mixed * @@ -477,6 +499,7 @@ class LogManager implements LoggerInterface * be logged and monitored. * * @param string $message + * @param array $context * * @return mixed * @@ -494,6 +517,7 @@ class LogManager implements LoggerInterface * that are not necessarily wrong. * * @param string $message + * @param array $context * * @return mixed * @@ -508,6 +532,7 @@ class LogManager implements LoggerInterface * Normal but significant events. * * @param string $message + * @param array $context * * @return mixed * @@ -524,6 +549,7 @@ class LogManager implements LoggerInterface * Example: User logs in, SQL logs. * * @param string $message + * @param array $context * * @return mixed * @@ -538,6 +564,7 @@ class LogManager implements LoggerInterface * Detailed debug information. * * @param string $message + * @param array $context * * @return mixed * @@ -553,6 +580,7 @@ class LogManager implements LoggerInterface * * @param mixed $level * @param string $message + * @param array $context * * @return mixed * diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Card.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Card.php index d5b259009..0e212312e 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Card.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Card.php @@ -42,6 +42,8 @@ class Card extends Message /** * Media constructor. + * + * @param string $cardId */ public function __construct(string $cardId) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Media.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Media.php index ab4447736..d8706fe88 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Media.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Media.php @@ -36,7 +36,9 @@ class Media extends Message implements MediaInterface /** * MaterialClient constructor. * + * @param string $mediaId * @param string $type + * @param array $attributes */ public function __construct(string $mediaId, $type = null, array $attributes = []) { @@ -46,6 +48,8 @@ class Media extends Message implements MediaInterface } /** + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ public function getMediaId(): string diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Message.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Message.php index 2c9d72fca..0c22aacd5 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Message.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Message.php @@ -12,9 +12,9 @@ namespace EasyWeChat\Kernel\Messages; use EasyWeChat\Kernel\Contracts\MessageInterface; -use EasyWeChat\Kernel\Exceptions\RuntimeException; use EasyWeChat\Kernel\Support\XML; use EasyWeChat\Kernel\Traits\HasAttributes; +use Mockery\Exception\BadMethodCallException; /** * Class Messages. @@ -23,24 +23,22 @@ abstract class Message implements MessageInterface { use HasAttributes; - public const TEXT = 2; - public const IMAGE = 4; - public const VOICE = 8; - public const VIDEO = 16; - public const SHORT_VIDEO = 32; - public const LOCATION = 64; - public const LINK = 128; - public const DEVICE_EVENT = 256; - public const DEVICE_TEXT = 512; - public const FILE = 1024; - public const TEXT_CARD = 2048; - public const TRANSFER = 4096; - public const EVENT = 1048576; - public const MINIPROGRAM_PAGE = 2097152; - public const MINIPROGRAM_NOTICE = 4194304; - public const ALL = self::TEXT | self::IMAGE | self::VOICE | self::VIDEO | self::SHORT_VIDEO | self::LOCATION | self::LINK - | self::DEVICE_EVENT | self::DEVICE_TEXT | self::FILE | self::TEXT_CARD | self::TRANSFER | self::EVENT - | self::MINIPROGRAM_PAGE | self::MINIPROGRAM_NOTICE; + const TEXT = 2; + const IMAGE = 4; + const VOICE = 8; + const VIDEO = 16; + const SHORT_VIDEO = 32; + const LOCATION = 64; + const LINK = 128; + const DEVICE_EVENT = 256; + const DEVICE_TEXT = 512; + const FILE = 1024; + const TEXT_CARD = 2048; + const TRANSFER = 4096; + const EVENT = 1048576; + const MINIPROGRAM_PAGE = 2097152; + const ALL = self::TEXT | self::IMAGE | self::VOICE | self::VIDEO | self::SHORT_VIDEO | self::LOCATION | self::LINK + | self::DEVICE_EVENT | self::DEVICE_TEXT | self::FILE | self::TEXT_CARD | self::TRANSFER | self::EVENT | self::MINIPROGRAM_PAGE; /** * @var string @@ -74,6 +72,8 @@ abstract class Message implements MessageInterface /** * Message constructor. + * + * @param array $attributes */ public function __construct(array $attributes = []) { @@ -82,12 +82,17 @@ abstract class Message implements MessageInterface /** * Return type name message. + * + * @return string */ public function getType(): string { return $this->type; } + /** + * @param string $type + */ public function setType(string $type) { $this->type = $type; @@ -129,6 +134,8 @@ abstract class Message implements MessageInterface } /** + * @param array $appends + * * @return array */ public function transformForJsonRequestWithoutType(array $appends = []) @@ -137,7 +144,10 @@ abstract class Message implements MessageInterface } /** - * @param bool $withType + * @param array $appends + * @param bool $withType + * + * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ @@ -154,6 +164,12 @@ abstract class Message implements MessageInterface return $data; } + /** + * @param array $appends + * @param bool $returnAsArray + * + * @return string + */ public function transformToXml(array $appends = [], bool $returnAsArray = false): string { $data = array_merge(['MsgType' => $this->getType()], $this->toXmlArray(), $appends); @@ -162,6 +178,11 @@ abstract class Message implements MessageInterface } /** + * @param array $data + * @param array $aliases + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ protected function propertiesToArray(array $data, array $aliases = []): array @@ -182,6 +203,6 @@ abstract class Message implements MessageInterface public function toXmlArray() { - throw new RuntimeException(sprintf('Class "%s" cannot support transform to XML message.', __CLASS__)); + throw new BadMethodCallException(sprintf('Class "%s" cannot support transform to XML message.', __CLASS__)); } } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/News.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/News.php index 33703d24f..2ad46e82d 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/News.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/News.php @@ -32,12 +32,20 @@ class News extends Message /** * News constructor. + * + * @param array $items */ public function __construct(array $items = []) { parent::__construct(compact('items')); } + /** + * @param array $data + * @param array $aliases + * + * @return array + */ public function propertiesToArray(array $data, array $aliases = []): array { return ['articles' => array_map(function ($item) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php index a3dd60948..53f2a78a5 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Raw.php @@ -30,6 +30,8 @@ class Raw extends Message /** * Constructor. + * + * @param string $content */ public function __construct(string $content) { @@ -37,7 +39,10 @@ class Raw extends Message } /** - * @param bool $withType + * @param array $appends + * @param bool $withType + * + * @return array */ public function transformForJsonRequest(array $appends = [], $withType = true): array { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Text.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Text.php index 7ce9df5ee..e355743f3 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Text.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Text.php @@ -34,6 +34,8 @@ class Text extends Message /** * Text constructor. + * + * @param string $content */ public function __construct(string $content) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php index fe7918b72..ff27d1a3f 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Transfer.php @@ -37,6 +37,8 @@ class Transfer extends Message /** * Transfer constructor. + * + * @param string|null $account */ public function __construct(string $account = null) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Messages/Video.php b/src/vendor/overtrue/wechat/src/Kernel/Messages/Video.php index 3ae48606c..90f72a0ac 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Messages/Video.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Messages/Video.php @@ -43,6 +43,9 @@ class Video extends Media /** * Video constructor. + * + * @param string $mediaId + * @param array $attributes */ public function __construct(string $mediaId, array $attributes = []) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php index 24ff91969..b33f4a133 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/ConfigServiceProvider.php @@ -32,7 +32,7 @@ class ConfigServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['config']) && $pimple['config'] = function ($app) { + $pimple['config'] = function ($app) { return new Config($app->getConfig()); }; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php index 97b2b99d5..9095cef7a 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/EventDispatcherServiceProvider.php @@ -32,7 +32,7 @@ class EventDispatcherServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['events']) && $pimple['events'] = function ($app) { + $pimple['events'] = function ($app) { $dispatcher = new EventDispatcher(); foreach ($app->config->get('events.listen', []) as $event => $listeners) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php index 1d8baddd8..23af8321e 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/ExtensionServiceProvider.php @@ -32,7 +32,7 @@ class ExtensionServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['extension']) && $pimple['extension'] = function ($app) { + $pimple['extension'] = function ($app) { return new Extension($app); }; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php index e21edfa29..aca7fa971 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/HttpClientServiceProvider.php @@ -32,7 +32,7 @@ class HttpClientServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['http_client']) && $pimple['http_client'] = function ($app) { + $pimple['http_client'] = function ($app) { return new Client($app['config']->get('http', [])); }; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php index fa15e6bea..83498ac60 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/LogServiceProvider.php @@ -32,7 +32,7 @@ class LogServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['log']) && $pimple['log'] = function ($app) { + $pimple['logger'] = $pimple['log'] = function ($app) { $config = $this->formatLogConfig($app); if (!empty($config)) { @@ -41,8 +41,6 @@ class LogServiceProvider implements ServiceProviderInterface return new LogManager($app); }; - - !isset($pimple['logger']) && $pimple['logger'] = $pimple['log']; } public function formatLogConfig($app) @@ -54,10 +52,11 @@ class LogServiceProvider implements ServiceProviderInterface if (empty($app['config']->get('log'))) { return [ 'log' => [ - 'default' => 'null', + 'default' => 'errorlog', 'channels' => [ - 'null' => [ - 'driver' => 'null', + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => 'debug', ], ], ], diff --git a/src/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php b/src/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php index d38522ea6..a0b111dd8 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Providers/RequestServiceProvider.php @@ -32,7 +32,7 @@ class RequestServiceProvider implements ServiceProviderInterface */ public function register(Container $pimple) { - !isset($pimple['request']) && $pimple['request'] = function () { + $pimple['request'] = function () { return Request::createFromGlobals(); }; } diff --git a/src/vendor/overtrue/wechat/src/Kernel/ServerGuard.php b/src/vendor/overtrue/wechat/src/Kernel/ServerGuard.php index 11d5399d3..c135e1275 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/ServerGuard.php +++ b/src/vendor/overtrue/wechat/src/Kernel/ServerGuard.php @@ -45,12 +45,12 @@ class ServerGuard /** * Empty string. */ - public const SUCCESS_EMPTY_RESPONSE = 'success'; + const SUCCESS_EMPTY_RESPONSE = 'success'; /** * @var array */ - public const MESSAGE_TYPE_MAPPING = [ + const MESSAGE_TYPE_MAPPING = [ 'text' => Message::TEXT, 'image' => Message::IMAGE, 'voice' => Message::VOICE, @@ -89,6 +89,8 @@ class ServerGuard /** * Handle and return response. * + * @return Response + * * @throws BadRequestException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -179,6 +181,8 @@ class ServerGuard /** * Resolve server request and return the response. * + * @return \Symfony\Component\HttpFoundation\Response + * * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -211,6 +215,8 @@ class ServerGuard } /** + * @param string $to + * @param string $from * @param \EasyWeChat\Kernel\Contracts\MessageInterface|string|int $message * * @return string @@ -245,6 +251,8 @@ class ServerGuard /** * Handle request. * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -266,6 +274,12 @@ class ServerGuard /** * Build reply XML. + * + * @param string $to + * @param string $from + * @param \EasyWeChat\Kernel\Contracts\MessageInterface $message + * + * @return string */ protected function buildReply(string $to, string $from, MessageInterface $message): string { @@ -287,6 +301,8 @@ class ServerGuard } /** + * @param array $params + * * @return string */ protected function signature(array $params) @@ -326,18 +342,25 @@ class ServerGuard /** * Check the request message safe mode. + * + * @return bool */ protected function isSafeMode(): bool { return $this->app['request']->get('signature') && 'aes' === $this->app['request']->get('encrypt_type'); } + /** + * @return bool + */ protected function shouldReturnRawResponse(): bool { return false; } /** + * @param array $message + * * @return mixed */ protected function decryptMessage(array $message) diff --git a/src/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php b/src/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php index 135093c82..af1f35bae 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php +++ b/src/vendor/overtrue/wechat/src/Kernel/ServiceContainer.php @@ -57,16 +57,20 @@ class ServiceContainer extends Container /** * Constructor. + * + * @param array $config + * @param array $prepends + * @param string|null $id */ public function __construct(array $config = [], array $prepends = [], string $id = null) { - $this->userConfig = $config; + $this->registerProviders($this->getProviders()); parent::__construct($prepends); - $this->id = $id; + $this->userConfig = $config; - $this->registerProviders($this->getProviders()); + $this->id = $id; $this->aggregate(); @@ -151,6 +155,9 @@ class ServiceContainer extends Container $this->offsetSet($id, $value); } + /** + * @param array $providers + */ public function registerProviders(array $providers) { foreach ($providers as $provider) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Support/AES.php b/src/vendor/overtrue/wechat/src/Kernel/Support/AES.php index 8aa169453..73b1b24f8 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Support/AES.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Support/AES.php @@ -18,6 +18,14 @@ namespace EasyWeChat\Kernel\Support; */ class AES { + /** + * @param string $text + * @param string $key + * @param string $iv + * @param int $option + * + * @return string + */ public static function encrypt(string $text, string $key, string $iv, int $option = OPENSSL_RAW_DATA): string { self::validateKey($key); @@ -27,7 +35,13 @@ class AES } /** + * @param string $cipherText + * @param string $key + * @param string $iv + * @param int $option * @param string|null $method + * + * @return string */ public static function decrypt(string $cipherText, string $key, string $iv, int $option = OPENSSL_RAW_DATA, $method = null): string { @@ -47,6 +61,9 @@ class AES return 'aes-'.(8 * strlen($key)).'-cbc'; } + /** + * @param string $key + */ public static function validateKey(string $key) { if (!in_array(strlen($key), [16, 24, 32], true)) { @@ -55,6 +72,8 @@ class AES } /** + * @param string $iv + * * @throws \InvalidArgumentException */ public static function validateIv(string $iv) diff --git a/src/vendor/overtrue/wechat/src/Kernel/Support/Arr.php b/src/vendor/overtrue/wechat/src/Kernel/Support/Arr.php index 00fd6543e..ac340386a 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Support/Arr.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Support/Arr.php @@ -19,6 +19,7 @@ class Arr /** * Add an element to an array using "dot" notation if it doesn't exist. * + * @param array $array * @param string $key * @param mixed $value * @@ -64,6 +65,8 @@ class Arr /** * Divide an array into two arrays. One with keys and the other with values. * + * @param array $array + * * @return array */ public static function divide(array $array) @@ -74,6 +77,7 @@ class Arr /** * Flatten a multi-dimensional associative array with dots. * + * @param array $array * @param string $prepend * * @return array @@ -96,6 +100,7 @@ class Arr /** * Get all of the given array except for a specified array of items. * + * @param array $array * @param array|string $keys * * @return array @@ -110,6 +115,7 @@ class Arr /** * Determine if the given key exists in the provided array. * + * @param array $array * @param string|int $key * * @return bool @@ -122,7 +128,9 @@ class Arr /** * Return the first element in an array passing a given truth test. * - * @param mixed $default + * @param array $array + * @param callable|null $callback + * @param mixed $default * * @return mixed */ @@ -150,7 +158,9 @@ class Arr /** * Return the last element in an array passing a given truth test. * - * @param mixed $default + * @param array $array + * @param callable|null $callback + * @param mixed $default * * @return mixed */ @@ -166,7 +176,8 @@ class Arr /** * Flatten a multi-dimensional array into a single level. * - * @param int $depth + * @param array $array + * @param int $depth * * @return array */ @@ -188,6 +199,7 @@ class Arr /** * Remove one or many array items from a given array using "dot" notation. * + * @param array $array * @param array|string $keys */ public static function forget(array &$array, $keys) @@ -230,6 +242,7 @@ class Arr /** * Get an item from an array using "dot" notation. * + * @param array $array * @param string $key * @param mixed $default * @@ -259,6 +272,7 @@ class Arr /** * Check if an item or items exist in an array using "dot" notation. * + * @param array $array * @param string|array $keys * * @return bool @@ -303,6 +317,8 @@ class Arr * * An array is "associative" if it doesn't have sequential numerical keys beginning with zero. * + * @param array $array + * * @return bool */ public static function isAssoc(array $array) @@ -315,6 +331,7 @@ class Arr /** * Get a subset of the items from the given array. * + * @param array $array * @param array|string $keys * * @return array @@ -327,6 +344,7 @@ class Arr /** * Push an item onto the beginning of an array. * + * @param array $array * @param mixed $value * @param mixed $key * @@ -346,6 +364,7 @@ class Arr /** * Get a value from the array, and remove it. * + * @param array $array * @param string $key * @param mixed $default * @@ -363,6 +382,9 @@ class Arr /** * Get a 1 value from an array. * + * @param array $array + * @param int|null $amount + * * @return mixed * * @throws \InvalidArgumentException @@ -389,7 +411,9 @@ class Arr * * If no key is given to the method, the entire array will be replaced. * - * @param mixed $value + * @param array $array + * @param string $key + * @param mixed $value * * @return array */ @@ -418,6 +442,9 @@ class Arr /** * Filter the array using the given callback. * + * @param array $array + * @param callable $callback + * * @return array */ public static function where(array $array, callable $callback) diff --git a/src/vendor/overtrue/wechat/src/Kernel/Support/Collection.php b/src/vendor/overtrue/wechat/src/Kernel/Support/Collection.php index f750e0bea..adf24eaef 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Support/Collection.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Support/Collection.php @@ -33,6 +33,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria /** * set data. + * + * @param array $items */ public function __construct(array $items = []) { @@ -54,6 +56,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria /** * Return specific items. * + * @param array $keys + * * @return \EasyWeChat\Kernel\Support\Collection */ public function only(array $keys) @@ -340,9 +344,9 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria * * @return array */ - public static function __set_state(array $properties) + public function __set_state() { - return (new static($properties))->all(); + return $this->all(); } /** diff --git a/src/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php b/src/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php index 6f1db32fc..08d4092e9 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Support/Helpers.php @@ -20,6 +20,7 @@ namespace EasyWeChat\Kernel\Support; /** * Generate a signature. * + * @param array $attributes * @param string $key * @param string $encryptMethod * @@ -35,6 +36,9 @@ function generate_sign(array $attributes, $key, $encryptMethod = 'md5') } /** + * @param string $signType + * @param string $secretKey + * * @return \Closure|string */ function get_encrypt_method(string $signType, string $secretKey = '') diff --git a/src/vendor/overtrue/wechat/src/Kernel/Support/XML.php b/src/vendor/overtrue/wechat/src/Kernel/Support/XML.php index b1318927c..93026e63c 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Support/XML.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Support/XML.php @@ -88,6 +88,7 @@ class XML /** * Object to array. * + * * @param SimpleXMLElement $obj * * @return array diff --git a/src/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php b/src/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php index 28dcf7a7c..238d9e28c 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Traits/HasAttributes.php @@ -33,6 +33,8 @@ trait HasAttributes /** * Set Attributes. * + * @param array $attributes + * * @return $this */ public function setAttributes(array $attributes = []) @@ -134,6 +136,8 @@ trait HasAttributes } /** + * @param string $key + * * @return bool */ public function has(string $key) @@ -142,6 +146,8 @@ trait HasAttributes } /** + * @param array $attributes + * * @return $this */ public function merge(array $attributes) diff --git a/src/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php b/src/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php index 1d05e2a0c..9bf0a023f 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Traits/HasHttpRequests.php @@ -61,6 +61,8 @@ trait HasHttpRequests /** * Return current guzzle default settings. + * + * @return array */ public static function getDefaultOptions(): array { @@ -70,6 +72,8 @@ trait HasHttpRequests /** * Set GuzzleHttp\Client. * + * @param \GuzzleHttp\ClientInterface $httpClient + * * @return $this */ public function setHttpClient(ClientInterface $httpClient) @@ -81,6 +85,8 @@ trait HasHttpRequests /** * Return GuzzleHttp\ClientInterface instance. + * + * @return ClientInterface */ public function getHttpClient(): ClientInterface { @@ -98,7 +104,8 @@ trait HasHttpRequests /** * Add a middleware. * - * @param string $name + * @param callable $middleware + * @param string $name * * @return $this */ @@ -115,6 +122,8 @@ trait HasHttpRequests /** * Return all middlewares. + * + * @return array */ public function getMiddlewares(): array { @@ -128,6 +137,8 @@ trait HasHttpRequests * @param string $method * @param array $options * + * @return \Psr\Http\Message\ResponseInterface + * * @throws \GuzzleHttp\Exception\GuzzleException */ public function request($url, $method = 'GET', $options = []): ResponseInterface @@ -149,6 +160,8 @@ trait HasHttpRequests } /** + * @param \GuzzleHttp\HandlerStack $handlerStack + * * @return $this */ public function setHandlerStack(HandlerStack $handlerStack) @@ -160,6 +173,8 @@ trait HasHttpRequests /** * Build a handler stack. + * + * @return \GuzzleHttp\HandlerStack */ public function getHandlerStack(): HandlerStack { @@ -176,6 +191,11 @@ trait HasHttpRequests return $this->handlerStack; } + /** + * @param array $options + * + * @return array + */ protected function fixJsonIssue(array $options): array { if (isset($options['json']) && is_array($options['json'])) { diff --git a/src/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php b/src/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php index ab26fe64a..6ee9e25e2 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Traits/InteractsWithCache.php @@ -95,6 +95,9 @@ trait InteractsWithCache return new FilesystemCache(); } + /** + * @return bool + */ protected function isSymfony43OrHigher(): bool { return \class_exists('Symfony\Component\Cache\Psr16Cache'); diff --git a/src/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php b/src/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php index 668d490cc..7db03f5aa 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Traits/Observable.php @@ -57,16 +57,6 @@ trait Observable return $this->newClause($handler); } - /** - * @return $this - */ - public function setHandlers(array $handlers = []) - { - $this->handlers = $handlers; - - return $this; - } - /** * @param \Closure|EventHandlerInterface|string $handler * @param \Closure|EventHandlerInterface|string $condition @@ -176,6 +166,8 @@ trait Observable /** * @param mixed $handler + * + * @return \EasyWeChat\Kernel\Clauses\Clause */ protected function newClause($handler): Clause { @@ -203,7 +195,8 @@ trait Observable } /** - * @param mixed $payload + * @param callable $handler + * @param mixed $payload * * @return mixed */ @@ -264,6 +257,8 @@ trait Observable * @param mixed $handler * @param mixed $condition * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \ReflectionException */ diff --git a/src/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php b/src/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php index 504b5eac5..5492bd464 100644 --- a/src/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php +++ b/src/vendor/overtrue/wechat/src/Kernel/Traits/ResponseCastable.php @@ -26,7 +26,8 @@ use Psr\Http\Message\ResponseInterface; trait ResponseCastable { /** - * @param string|null $type + * @param \Psr\Http\Message\ResponseInterface $response + * @param string|null $type * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Application.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Application.php index 2d5976ca2..cd455fb30 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Application.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Application.php @@ -114,6 +114,9 @@ class Application extends ServiceContainer /** * setCertificate. * + * @param string $certificate + * @param string $serialNo + * * @return $this */ public function setCertificate(string $certificate, string $serialNo) @@ -129,6 +132,8 @@ class Application extends ServiceContainer * returning false indicates that the signature field does not exist or is empty, * and if the signature verification is wrong, the InvalidSignException will be thrown directly. * + * @param array $data + * * @return bool * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php index 349364912..ba9275648 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Base/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * apply to settle in to become a small micro merchant. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -46,6 +48,9 @@ class Client extends BaseClient /** * query application status. * + * @param string $applymentId + * @param string $businessCode + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -76,6 +81,8 @@ class Client extends BaseClient /** * merchant upgrade api. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -99,6 +106,8 @@ class Client extends BaseClient /** * get upgrade status. * + * @param string $subMchId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php index 2b091452e..62a6cf563 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Certficates/Client.php @@ -26,6 +26,8 @@ class Client extends BaseClient /** * get certficates. * + * @param bool $returnRaw + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -63,6 +65,8 @@ class Client extends BaseClient /** * decrypt ciphertext. * + * @param array $encryptCertificate + * * @return string * * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php index fa1e796d8..d91b4677f 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Kernel/BaseClient.php @@ -32,6 +32,8 @@ class BaseClient extends PaymentBaseClient /** * BaseClient constructor. + * + * @param \EasyWeChat\MicroMerchant\Application $app */ public function __construct(Application $app) { @@ -53,7 +55,11 @@ class BaseClient extends PaymentBaseClient /** * httpUpload. * - * @param bool $returnResponse + * @param string $url + * @param array $files + * @param array $form + * @param array $query + * @param bool $returnResponse * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @@ -113,7 +119,10 @@ class BaseClient extends PaymentBaseClient /** * request. * + * @param string $endpoint + * @param array $params * @param string $method + * @param array $options * @param bool $returnResponse * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string @@ -151,6 +160,8 @@ class BaseClient extends PaymentBaseClient /** * processing parameters contain fields that require sensitive information encryption. * + * @param array $params + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -177,6 +188,8 @@ class BaseClient extends PaymentBaseClient /** * To id card, mobile phone number and other fields sensitive information encryption. * + * @param string $string + * * @return string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -224,6 +237,8 @@ class BaseClient extends PaymentBaseClient /** * getSign. * + * @param array $params + * * @return string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php index eb7a0d805..ee1038af2 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Material/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * update settlement card. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -47,6 +49,8 @@ class Client extends BaseClient /** * update contact info. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php b/src/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php index 7d8e83c55..fde755bca 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/Media/Client.php @@ -25,6 +25,8 @@ class Client extends BaseClient /** * Upload material. * + * @param string $path + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php b/src/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php index e72cc918d..c8573afd5 100644 --- a/src/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php +++ b/src/vendor/overtrue/wechat/src/MicroMerchant/MerchantConfig/Client.php @@ -24,6 +24,11 @@ class Client extends BaseClient /** * Service providers configure recommendation functions for small and micro businesses. * + * @param string $subAppId + * @param string $subscribeAppId + * @param string $receiptAppId + * @param string $subMchId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -52,6 +57,10 @@ class Client extends BaseClient /** * Configure the new payment directory. * + * @param string $jsapiPath + * @param string $appId + * @param string $subMchId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -69,6 +78,10 @@ class Client extends BaseClient /** * bind appid. * + * @param string $subAppId + * @param string $appId + * @param string $subMchId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -86,6 +99,8 @@ class Client extends BaseClient /** * add sub dev config. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -100,6 +115,9 @@ class Client extends BaseClient /** * query Sub Dev Config. * + * @param string $subMchId + * @param string $appId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/ActivityMessage/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/ActivityMessage/Client.php index 2cbfa0854..16f273d70 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/ActivityMessage/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/ActivityMessage/Client.php @@ -27,6 +27,10 @@ class Client extends BaseClient } /** + * @param string $activityId + * @param int $state + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -51,6 +55,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/AppCode/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/AppCode/Client.php index b9df3bcc6..82d2af2c3 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/AppCode/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/AppCode/Client.php @@ -24,6 +24,9 @@ class Client extends BaseClient /** * Get AppCode. * + * @param string $path + * @param array $optional + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string */ public function get(string $path, array $optional = []) @@ -38,6 +41,9 @@ class Client extends BaseClient /** * Get AppCode unlimit. * + * @param string $scene + * @param array $optional + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string */ public function getUnlimit(string $scene, array $optional = []) @@ -52,6 +58,9 @@ class Client extends BaseClient /** * Create QrCode. * + * @param string $path + * @param int|null $width + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string */ public function getQrCode(string $path, int $width = null) @@ -62,6 +71,9 @@ class Client extends BaseClient /** * Get stream. * + * @param string $endpoint + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Application.php b/src/vendor/overtrue/wechat/src/MiniProgram/Application.php index ee655a738..93b492fe8 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Application.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Application.php @@ -38,11 +38,12 @@ use EasyWeChat\Kernel\ServiceContainer; * @property \EasyWeChat\BasicService\Media\Client $media * @property \EasyWeChat\BasicService\ContentSecurity\Client $content_security * @property \EasyWeChat\MiniProgram\Mall\ForwardsMall $mall + * @property \EasyWeChat\MiniProgram\Live\Live $live * @property \EasyWeChat\MiniProgram\SubscribeMessage\Client $subscribe_message * @property \EasyWeChat\MiniProgram\RealtimeLog\Client $realtime_log * @property \EasyWeChat\MiniProgram\Search\Client $search - * @property \EasyWeChat\MiniProgram\Live\Client $live - * @property \EasyWeChat\MiniProgram\Broadcast\Client $broadcast + * @property \EasyWeChat\MiniProgram\Ministore\Client $mini_store + * @property \EasyWeChat\MiniProgram\OrderShipping\Client $order_shipping */ class Application extends ServiceContainer { @@ -66,14 +67,17 @@ class Application extends ServiceContainer OCR\ServiceProvider::class, Soter\ServiceProvider::class, Mall\ServiceProvider::class, + Live\ServiceProvider::class, SubscribeMessage\ServiceProvider::class, RealtimeLog\ServiceProvider::class, Search\ServiceProvider::class, - Live\ServiceProvider::class, - Broadcast\ServiceProvider::class, // Base services BasicService\Media\ServiceProvider::class, BasicService\ContentSecurity\ServiceProvider::class, + //todo 周 新增视频号 + Ministore\ServiceProvider::class, + //小程序发货信息管理 + OrderShipping\ServiceProvider::class ]; /** diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Auth/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/Auth/Client.php index 313120839..a79c92907 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Auth/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Auth/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Get session info by code. * + * @param string $code + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -38,4 +40,19 @@ class Client extends BaseClient return $this->httpGet('sns/jscode2session', $params); } + + /** + * 获取手机号 + * @param string $code + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function phoneNumber(string $code) + { + $params = [ + 'code' => $code + ]; + return $this->httpPostJson('wxa/business/getuserphonenumber', $params); + } } diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/DataCube/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/DataCube/Client.php index 0430d711d..8a10b7ece 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/DataCube/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/DataCube/Client.php @@ -23,6 +23,9 @@ class Client extends BaseClient /** * Get summary trend. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function summaryTrend(string $from, string $to) @@ -33,6 +36,9 @@ class Client extends BaseClient /** * Get daily visit trend. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function dailyVisitTrend(string $from, string $to) @@ -43,6 +49,9 @@ class Client extends BaseClient /** * Get weekly visit trend. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function weeklyVisitTrend(string $from, string $to) @@ -53,6 +62,9 @@ class Client extends BaseClient /** * Get monthly visit trend. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function monthlyVisitTrend(string $from, string $to) @@ -63,6 +75,9 @@ class Client extends BaseClient /** * Get visit distribution. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function visitDistribution(string $from, string $to) @@ -73,6 +88,9 @@ class Client extends BaseClient /** * Get daily retain info. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function dailyRetainInfo(string $from, string $to) @@ -83,6 +101,9 @@ class Client extends BaseClient /** * Get weekly retain info. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function weeklyRetainInfo(string $from, string $to) @@ -93,6 +114,9 @@ class Client extends BaseClient /** * Get monthly retain info. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function monthlyRetainInfo(string $from, string $to) @@ -103,6 +127,9 @@ class Client extends BaseClient /** * Get visit page. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function visitPage(string $from, string $to) @@ -113,6 +140,9 @@ class Client extends BaseClient /** * Get user portrait. * + * @param string $from + * @param string $to + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function userPortrait(string $from, string $to) @@ -123,6 +153,10 @@ class Client extends BaseClient /** * Unify query. * + * @param string $api + * @param string $from + * @param string $to + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Encryptor.php b/src/vendor/overtrue/wechat/src/MiniProgram/Encryptor.php index 28a2dd887..167a2a087 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Encryptor.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Encryptor.php @@ -25,17 +25,21 @@ class Encryptor extends BaseEncryptor /** * Decrypt data. * + * @param string $sessionKey + * @param string $iv + * @param string $encrypted + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\DecryptException */ public function decryptData(string $sessionKey, string $iv, string $encrypted): array { $decrypted = AES::decrypt( - base64_decode($encrypted, false), - base64_decode($sessionKey, false), - base64_decode($iv, false) + base64_decode($encrypted, false), base64_decode($sessionKey, false), base64_decode($iv, false) ); - $decrypted = json_decode($decrypted, true); + $decrypted = json_decode($this->pkcs7Unpad($decrypted), true); if (!$decrypted) { throw new DecryptException('The given payload is invalid.'); diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Express/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/Express/Client.php index 342ebd527..a0311c88f 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Express/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Express/Client.php @@ -31,6 +31,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +44,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -53,6 +57,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -64,6 +70,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -75,6 +83,9 @@ class Client extends BaseClient } /** + * @param string $deliveryId + * @param string $bizId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -89,17 +100,8 @@ class Client extends BaseClient } /** - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @param string $openid * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function getPrinter() - { - return $this->httpPostJson('cgi-bin/express/business/printer/getall'); - } - - /** * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -114,6 +116,8 @@ class Client extends BaseClient } /** + * @param string $openid + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Live/GoodsClient.php b/src/vendor/overtrue/wechat/src/MiniProgram/Live/GoodsClient.php new file mode 100644 index 000000000..3bd43da8b --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Live/GoodsClient.php @@ -0,0 +1,99 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\Live; + +use EasyWeChat\Kernel\BaseClient; + +/** + * Class Client. + * + * @author mingyoung + */ +class GoodsClient extends BaseClient +{ + /** + * 商品添加并提审 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function add($param) { + return $this->httpPostJson('wxaapi/broadcast/goods/add', $param); + } + + /** + * 撤回审核 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function resetAudit($param) { + return $this->httpPostJson('wxaapi/broadcast/goods/resetaudit', $param); + } + + /** + * 重新提交审核 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function audit($param) { + return $this->httpPostJson('wxaapi/broadcast/goods/audit', $param); + } + + /** + * 删除商品 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function delete($param) { + return $this->httpPostJson('wxaapi/broadcast/goods/delete', $param); + } + + /** + * 更新商品 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function update($param) { + return $this->httpPostJson('wxaapi/broadcast/goods/update', $param); + } + + /** + * 获取商品状态 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getStatus($param) { + return $this->httpPostJson('wxa/business/getgoodswarehouse', $param); + } + + /** + * 获取商品列表 + * @param $param + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getGoodsList($param) { + return $this->httpGet('wxaapi/broadcast/goods/getapproved', $param); + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Live/Live.php b/src/vendor/overtrue/wechat/src/MiniProgram/Live/Live.php new file mode 100644 index 000000000..ae1a19c62 --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Live/Live.php @@ -0,0 +1,46 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\Live; + +/** + * Class Application. + * + * @author mingyoung + * + * @property \EasyWeChat\MiniProgram\Live\GoodsClient $goods + * @property \EasyWeChat\MiniProgram\Live\RoomClient $room + */ +class Live +{ + /** + * @var \EasyWeChat\Kernel\ServiceContainer + */ + protected $app; + + /** + * @param \EasyWeChat\Kernel\ServiceContainer $app + */ + public function __construct($app) + { + $this->app = $app; + } + + /** + * @param string $property + * + * @return mixed + */ + public function __get($property) + { + return $this->app["live.{$property}"]; + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Live/RoomClient.php b/src/vendor/overtrue/wechat/src/MiniProgram/Live/RoomClient.php new file mode 100644 index 000000000..72dd04df9 --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Live/RoomClient.php @@ -0,0 +1,55 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\Live; + +use EasyWeChat\Kernel\BaseClient; + +/** + * Class Client. + * + * @author mingyoung + */ +class RoomClient extends BaseClient +{ + /** + * 获取直播房间列表 或 获取回放源视频 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getLiveInfo($params){ + return $this->httpPostJson('wxa/business/getliveinfo', $params); + } + + /** + * 创建直播间 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function create($params){ + return $this->httpPostJson('wxaapi/broadcast/room/create', $params); + } + + /** + * 往指定直播间导入已入库商品 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function addGoods($params){ + return $this->httpPostJson('wxaapi/broadcast/room/addgoods', $params); + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Live/ServiceProvider.php b/src/vendor/overtrue/wechat/src/MiniProgram/Live/ServiceProvider.php index 6d6dff61f..c185f7aaa 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Live/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Live/ServiceProvider.php @@ -14,11 +14,6 @@ namespace EasyWeChat\MiniProgram\Live; use Pimple\Container; use Pimple\ServiceProviderInterface; -/** - * Class ServiceProvider. - * - * @author onekb <1@1kb.ren> - */ class ServiceProvider implements ServiceProviderInterface { /** @@ -27,7 +22,15 @@ class ServiceProvider implements ServiceProviderInterface public function register(Container $app) { $app['live'] = function ($app) { - return new Client($app); + return new Live($app); + }; + + $app['live.goods'] = function ($app) { + return new GoodsClient($app); + }; + + $app['live.room'] = function ($app) { + return new RoomClient($app); }; } } diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Mall/CartClient.php b/src/vendor/overtrue/wechat/src/MiniProgram/Mall/CartClient.php index ddf05877f..7a07e7714 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Mall/CartClient.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Mall/CartClient.php @@ -70,6 +70,7 @@ class CartClient extends BaseClient * 删除收藏. * * @param string $openid + * @param array $products * * @return mixed * diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/Client.php new file mode 100644 index 000000000..79153879e --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/Client.php @@ -0,0 +1,504 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\Ministore; + +use EasyWeChat\Kernel\BaseClient; +use EasyWeChat\Kernel\Exceptions\InvalidArgumentException; + +class Client extends BaseClient +{ + /************************************************************ 接入申请 *********************************************************/ + /** + * 申请接入 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function apply(){ + return $this->httpPostJson('shop/register/apply', []); + } + + /** + * 完成接入任务 + * @param int $access_info_item + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function finish_access_info(int $access_info_item){ + return $this->httpPostJson('shop/register/finish_access_info', ['access_info_item' => $access_info_item]); + } + + /** + * 获取接入状态 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function check(){ + return $this->httpPostJson('shop/register/check', []); + } + + /************************************************************ 类目 *********************************************************/ + /** + * 获取所有类目的详情 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function get(){ + return $this->httpPostJson('shop/cat/get', []); + } + + + /** + * 品牌审核 + * @param array $audit_req + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function auditbrand(array $audit_req){ + $params = [ + 'audit_req' => $audit_req + ]; + + return $this->httpPostJson('shop/audit/audit_brand', $params); + } + + /** + * 类目审核 + * @param array $audit_req + */ + public function auditCategory(array $audit_req){ + $params = [ + 'audit_req' => $audit_req + ]; + + return $this->httpPostJson('shop/audit/audit_category', $params); + } + + /** + * 获取审核结果 + * @param $audit_id + */ + public function auditResult($audit_id){ + $params = [ + 'audit_id' => $audit_id + ]; + + return $this->httpPostJson('shop/audit/result', $params); + } + + /** + *获取小程序资质 + * @param $req_type + */ + public function getMiniappCertificate($req_type){ + $params = [ + 'req_type' => $req_type + ]; + + return $this->httpPostJson('shop/audit/get_miniapp_certificate', $params); + } + /************************************************************ 商家入驻查询 *********************************************************/ + /** + *获取商家类目列表 + */ + public function getCategoryList(){ + $params = []; + return $this->httpPostJson('shop/account/get_category_list', $params); + } + /************************************************************ SPU *********************************************************/ + /** + * 添加spu + * @param $params + */ + public function addSpu($params){ + return $this->httpPostJson('shop/spu/add', $params); + } + + /** + * 删除spu + * @param $product_id + * @param $out_product_id + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function delSpu($product_id, $out_product_id){ + $params = array( + 'product_id' => $product_id, + 'out_product_id' => $out_product_id + ); + return $this->httpPostJson('shop/spu/del', $params); + } + + /** + * 撤回商品审核 + * @param $product_id + * @param $out_product_id + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function delSpuAudit($product_id, $out_product_id){ + $params = array( + 'product_id' => $product_id, + 'out_product_id' => $out_product_id + ); + return $this->httpPostJson('shop/spu/del_audit', $params); + } + + /** + * 获取商品 + * @param $product_id + * @param $out_product_id + * @param int $need_edit_spu + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getSpu($product_id, $out_product_id, $need_edit_spu = 0){ + $params = array( + 'product_id' => $product_id, + 'out_product_id' => $out_product_id, + 'need_edit_spu' => $need_edit_spu + ); + return $this->httpPostJson('shop/spu/del_audit', $params); + } + + /** + * 获取商品列表 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getSpuList($params){ + return $this->httpPostJson('shop/spu/get_list', $params); + } + + + /** + * 更新商品 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function updateSpu($params){ + return $this->httpPostJson('shop/spu/update', $params); + } + + /** + * 上架商品 + * @param $product_id + * @param $out_product_id + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function listingSpu($product_id, $out_product_id){ + $params = array( + 'product_id' => $product_id, + 'out_product_id' => $out_product_id + ); + return $this->httpPostJson('shop/spu/listing', $params); + } + + /** + * 下架商品 + * @param $product_id + * @param $out_product_id + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function delistingSpu($product_id, $out_product_id){ + $params = array( + 'product_id' => $product_id, + 'out_product_id' => $out_product_id + ); + return $this->httpPostJson('shop/spu/delisting', $params); + } + + /**************************************************************** 订单接口 *********************************************************/ + + /** + * 检查场景值是否在支付校验范围内 + * @param $scene + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function checkScene($scene){ + $params = array( + 'scene' => $scene + ); + return $this->httpPostJson('shop/scene/check', $params); + } + + /** + * 生成订单 + * @param $params + */ + public function addOrder($params){ + + return $this->httpPostJson('shop/order/add', $params); + } + + /** + * 同步订单支付结果 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function payOrder($params){ + return $this->httpPostJson('shop/order/pay', $params); + } + + /** + * 获取订单详情 + * @param $order_id + * @param $out_order_id + * @param $openid + */ + public function getOrder($order_id, $out_order_id, $openid){ + $params = array( + 'order_id' => $order_id, + 'out_order_id' => $out_order_id, + 'openid' => $openid, + ); + return $this->httpPostJson('shop/order/get', $params); + } + + + /**************************************************************** 物流接口 *********************************************************/ + + /** + * 获取快递公司列表 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getDeliveryCompanyList(){ + $params = []; + return $this->httpPostJson('shop/delivery/get_company_list', $params); + } + + /** + * 订单发货 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function sendDelivery($order_id, $out_order_id, $openid, $finish_all_delivery = 0, $delivery_list){ + $params = array( + 'order_id' => $order_id, + 'out_order_id' => $out_order_id, + 'openid' => $openid, + 'finish_all_delivery' => $finish_all_delivery, + 'delivery_list' => $delivery_list, + 'ship_done_time' => date("Y-m-d H:i:s", time()) + ); + return $this->httpPostJson('shop/delivery/send', $params); + } + + /** + * 订单收货 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function recieveDelivery($order_id, $out_order_id, $openid){ + $params = array( + 'order_id' => $order_id, + 'out_order_id' => $out_order_id, + 'openid' => $openid, + ); + return $this->httpPostJson('shop/delivery/recieve', $params); + } + /**************************************************************** 售后接口 *********************************************************/ + + /** + * 创建售后 + * @param $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function addAftersale($params){ + return $this->httpPostJson('shop/ecaftersale/add', $params); + } + + /** + * 获取售后 + * @param $order_id + * @param $out_order_id + * @param $openid + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getAftersale($params){ + return $this->httpPostJson('shop/ecaftersale/get', $params); + } + + /** + * 更新售后 + * @param $order_id + * @param $out_order_id + * @param $openid + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function updateAftersale($params){ + return $this->httpPostJson('shop/ecaftersale/update', $params); + } + + + + + + + /** + * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string + * + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + */ + public function createActivityId() + { + return $this->httpGet('cgi-bin/message/wxopen/activityid/create'); + } + + /** + * @param string $activityId + * @param int $state + * @param array $params + * + * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string + * + * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function updateMessage(string $activityId, int $state = 0, array $params = []) + { + if (!in_array($state, [0, 1], true)) { + throw new InvalidArgumentException('"state" should be "0" or "1".'); + } + + $params = $this->formatParameters($params); + + $params = [ + 'activity_id' => $activityId, + 'target_state' => $state, + 'template_info' => ['parameter_list' => $params], + ]; + + return $this->httpPostJson('cgi-bin/message/wxopen/updatablemsg/send', $params); + } + + /** + * @param array $params + * + * @return array + * + * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException + */ + protected function formatParameters(array $params) + { + $formatted = []; + + foreach ($params as $name => $value) { + if (!in_array($name, ['member_count', 'room_limit', 'path', 'version_type'], true)) { + continue; + } + + if ('version_type' === $name && !in_array($value, ['develop', 'trial', 'release'], true)) { + throw new InvalidArgumentException('Invalid value of attribute "version_type".'); + } + + $formatted[] = [ + 'name' => $name, + 'value' => strval($value), + ]; + } + + return $formatted; + } + + /** + * 获取图片 + * @param $audit_id + */ + public function uploadImg($url){ + $params = [ + ['name' => 'img_url', 'contents' => $url], + ['name' => 'resp_type', 'contents' => 1], + ['name' => 'upload_type', 'contents' => 1], + ]; + return $this->request('shop/img/upload', 'POST', ['multipart' => $params]); + } + + public function updateShop($params){ + + return $this->httpPostJson('shop/account/update_info', $params); + } + + /** + * 视频号订单同步订单结果 + */ + public function updateOrderType($params){ + + return $this->httpPostJson('shop/order/pay', $params); + } + + //获取支付参数 + public function getPaymentParams($params){ + return $this->httpPostJson('shop/order/getpaymentparams', $params); + } + + //同意退款 + public function orderRefund($params){ + return $this->httpPostJson('shop/ecaftersale/acceptrefund', $params); + } + + //拒绝退款 + public function orderNoRefund($params){ + return $this->httpPostJson('shop/ecaftersale/reject', $params); + } + + //同意退货 + public function aceptreturn($params){ + return $this->httpPostJson('shop/ecaftersale/acceptreturn', $params); + } + + //取消售后 + public function cancel($params){ + return $this->httpPostJson('shop/ecaftersale/cancel', $params); + } + + //买家发货 + public function uploadreturninfo($params){ + return $this->httpPostJson('shop/ecaftersale/uploadreturninfo', $params); + } + + public function getOrderList($params){ + return $this->httpPostJson('shop/ecaftersale/get_list', ['offset' => 0, 'limit' => 50]); + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/ServiceProvider.php b/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/ServiceProvider.php new file mode 100644 index 000000000..e95dc67bd --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Ministore/ServiceProvider.php @@ -0,0 +1,28 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\Ministore; + +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +class ServiceProvider implements ServiceProviderInterface +{ + /** + * {@inheritdoc}. + */ + public function register(Container $app) + { + $app['mini_store'] = function ($app) { + return new Client($app); + }; + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/NearbyPoi/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/NearbyPoi/Client.php index b5e17de2a..da9ee05f2 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/NearbyPoi/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/NearbyPoi/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * Add nearby poi. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +44,9 @@ class Client extends BaseClient /** * Update nearby poi. * + * @param string $poiId + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -60,6 +65,8 @@ class Client extends BaseClient /** * Delete nearby poi. * + * @param string $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -75,6 +82,9 @@ class Client extends BaseClient /** * Get nearby poi list. * + * @param int $page + * @param int $pageRows + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -90,6 +100,9 @@ class Client extends BaseClient /** * Set nearby poi show status. * + * @param string $poiId + * @param int $status + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/OpenData/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/OpenData/Client.php index 73944dc02..c9472c646 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/OpenData/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/OpenData/Client.php @@ -28,6 +28,10 @@ class Client extends BaseClient /** * removeUserStorage. * + * @param string $openid + * @param string $sessionKey + * @param array $key + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -48,6 +52,10 @@ class Client extends BaseClient /** * setUserStorage. * + * @param string $openid + * @param string $sessionKey + * @param array $kvList + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -68,6 +76,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return array */ protected function formatKVLists(array $params) diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/Client.php new file mode 100644 index 000000000..b197b21be --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/Client.php @@ -0,0 +1,171 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\OrderShipping; + +use EasyWeChat\Kernel\BaseClient; +use EasyWeChat\Kernel\Exceptions\InvalidArgumentException; + +/** + * 小程序发货信息管理服务 + * Class Client + * @package EasyWeChat\MiniProgram\OrderShipping + */ +class Client extends BaseClient +{ + + /** + * 查询小程序是否已开通发货信息管理服务 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#七、查询小程序是否已开通发货信息管理服务 + * 返回结果:{"errcode":0,"errmsg":"ok","is_trade_managed":true} + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function isTradeManaged() + { + return $this->httpPostJson('wxa/sec/order/is_trade_managed', [ 'appid' => $this->app[ 'config' ]->app_id ]); + } + + /** + * 发货信息录入接口 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#一、发货信息录入接口 + * 用户交易后,默认资金将会进入冻结状态,开发者在发货后,需要在小程序平台录入相关发货信息,平台会将发货信息以消息的形式推送给购买的微信用户。 + * 如果你已经录入发货信息,在用户尚未确认收货的情况下可以通过该接口修改发货信息,但一个支付单只能更新一次发货信息,请谨慎操作。 + * 如暂时没有完成相关API的对接开发工作,你也可以登陆小程序的后台,通过发货信息管理页面手动录入发货信息。 + * 注意事项 + * 1、根据指定的订单单号类型,采用不同参数给指定订单上传物流信息: + * (1). 商户侧单号形式(枚举值1),通过下单商户号和商户侧单号确定一笔订单 + * (2). 微信支付单号形式(枚举值2),通过微信支付单号确定一笔订单 + * 2、发货模式根据具体发货情况选择: + * (1). 统一发货(枚举值1),一笔订单统一发货,只有一个物流单号。 + * (2). 分拆发货(枚举值2),一笔订单分拆发货,包括多个物流单号。 + * 3、物流公司编码,参见获取运力 id 列表get_delivery_list。 + * https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/express_search.html#%E8%8E%B7%E5%8F%96%E8%BF%90%E5%8A%9Bid%E5%88%97%E8%A1%A8get-delivery-list + * 4、上传时间,用于标识请求的先后顺序,如果要更新物流信息,上传时间必须比之前的请求更新,请按照 RFC 3339 格式填写。 + * 5、分拆发货仅支持使用物流快递发货,一笔支付单最多分拆成 10 个包裹。 + * 6、以下情况将视为重新发货,每笔支付单仅有一次重新发货机会。 + * (1). 对已完成发货的支付单再次调用该 API。 + * (2). 使用该 API 修改发货模式或物流模式。 + * @param array $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function uploadShippingInfo(array $params = []) + { + return $this->httpPostJson('wxa/sec/order/upload_shipping_info', $params); + } + + /** + * 发货信息合单录入接口 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#二、发货信息合单录入接口 + * 用户交易后,默认资金将会进入冻结状态,开发者在发货后,需要在小程序平台录入相关发货信息,平台会将发货信息以消息的形式推送给购买的微信用户。 + * 如果你已经录入发货信息,在用户尚未确认收货的情况下可以通过该接口修改发货信息,但一个支付单只能更新一次发货信息,请谨慎操作。 + * 如暂时没有完成相关API的对接开发工作,你也可以登陆小程序的后台,通过发货信息录入页面手动录入发货信息。 + * 注意事项 + * 1、根据指定的订单单号类型,采用不同参数给指定订单上传物流信息,注意子单和主单的订单单号类型必须一致: + * (1). 商户侧单号形式(枚举值1),通过下单商户号和商户侧单号确定一笔订单 + * (2). 微信支付单号形式(枚举值2),通过微信支付单号确定一笔订单 + * 2、发货模式根据具体发货情况选择: + * (1). 统一发货(枚举值1),一笔订单统一发货,只有一个物流单号。 + * (2). 分拆发货(枚举值2),一笔订单分拆发货,包括多个物流单号。 + * 3、物流公司编码,参见获取运力 id 列表get_delivery_list。 + * 4、上传时间,用于标识请求的先后顺序,如果要更新物流信息,上传时间必须比之前的请求更新,请按照RFC 3339格式填写。 + * 5、分拆发货仅支持使用物流快递发货,一笔支付单最多分拆成 10 个包裹。 + * 6、以下情况将视为重新发货,每笔支付单仅有一次重新发货机会。 + * (1). 对已完成发货的支付单再次调用该 API。 + * (2). 使用该 API 修改发货模式或物流模式。 + * @param array $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function uploadCombinedShippingInfo(array $params = []) + { + return $this->httpPostJson('wxa/sec/order/upload_combined_shipping_info', $params); + } + + /** + * 查询订单发货状态 + * 你可以通过交易单号或商户号+商户单号来查询该支付单的发货状态。 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#三、查询订单发货状态 + * @param array $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getOrder(array $params = []) + { + return $this->httpPostJson('wxa/sec/order/get_order', $params); + } + + /** + * 查询订单列表 + * 你可以通过支付时间、支付者openid或订单状态来查询订单列表。 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#四、查询订单列表 + * @param array $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getOrderList(array $params = []) + { + return $this->httpPostJson('wxa/sec/order/get_order_list', $params); + } + + /** + * 确认收货提醒接口 + * 文档:https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#五、确认收货提醒接口 + * 如你已经从你的快递物流服务方获知到用户已经签收相关商品,可以通过该接口提醒用户及时确认收货,以提高资金结算效率,每个订单仅可调用一次。 + * 注意事项 + * 1、通过交易单号或商户号+商户单号来指定订单。 + * 2、只有物流类型为物流快递时才能进行提醒。 + * 3、签收时间由商户传入,在给用户发送提醒消息时会显示签收时间,签收时间必须在发货时间之后。 + * @param array $params + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function notifyConfirmReceive(array $params = []) + { + return $this->httpPostJson('wxa/sec/order/notify_confirm_receive', $params); + } + + /** + * 消息跳转路径设置接口 + * 如你已经在小程序内接入平台提供的确认收货组件,可以通过该接口设置发货消息及确认收货消息的跳转动作,用户点击发货消息时会直接进入你的小程序订单列表页面或详情页面进行确认收货,进一步优化用户体验。 + * 注意事项 + * 1、如设置为空路径或小程序中不存在的路径,将仍然跳转平台默认的确认收货页面,不会进入你的小程序。 + * 2、平台会在路径后面增加支付单的 transaction_id、merchant_id、merchant_trade_no 作为query参数,如果存在二级商户号则还会再增加 sub_merchant_id 参数,开发者可以在小程序中通过onLaunch等方式获取。 + * 3、如你需要在path中携带自定义的query参数,请注意与上面的参数进行区分 + * @param string $path 商户自定义跳转路径 + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function setMsgJumpPath($path) + { + return $this->httpPostJson('wxa/sec/order/set_msg_jump_path', [ 'path' => $path ]); + } + + /** + * 获取物流公司,运力id列表get_delivery_list + * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string + * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function getDeliveryList() + { + return $this->httpPostJson('cgi-bin/express/delivery/open_msg/get_delivery_list'); + } + +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/ServiceProvider.php b/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/ServiceProvider.php new file mode 100644 index 000000000..7d065fba9 --- /dev/null +++ b/src/vendor/overtrue/wechat/src/MiniProgram/OrderShipping/ServiceProvider.php @@ -0,0 +1,28 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace EasyWeChat\MiniProgram\OrderShipping; + +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +class ServiceProvider implements ServiceProviderInterface +{ + /** + * {@inheritdoc}. + */ + public function register(Container $app) + { + $app['order_shipping'] = function ($app) { + return new Client($app); + }; + } +} diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/DevClient.php b/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/DevClient.php index 663501bfc..3f25edce3 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/DevClient.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/DevClient.php @@ -23,6 +23,9 @@ class DevClient extends BaseClient /** * Get users. * + * @param int $page + * @param int $size + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -40,6 +43,8 @@ class DevClient extends BaseClient /** * Agree to use plugin. * + * @param string $appId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -56,6 +61,8 @@ class DevClient extends BaseClient /** * Refuse to use plugin. * + * @param string $reason + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/ServiceProvider.php b/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/ServiceProvider.php index d2c683716..097c77e43 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Plugin/ServiceProvider.php @@ -26,6 +26,8 @@ class ServiceProvider implements ServiceProviderInterface * * This method should only be used to configure services and parameters. * It should not get services. + * + * @param \Pimple\Container $app */ public function register(Container $app) { diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/RealtimeLog/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/RealtimeLog/Client.php index eda114fe1..936361924 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/RealtimeLog/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/RealtimeLog/Client.php @@ -23,6 +23,11 @@ class Client extends BaseClient /** * Real time log query. * + * @param string $date + * @param int $beginTime + * @param int $endTime + * @param array $options + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Search/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/Search/Client.php index 81bc42dfc..038cf9112 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Search/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Search/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Submit applet page URL and parameter information. * + * @param array $pages + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/Soter/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/Soter/Client.php index 287fd222d..cdf66d761 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/Soter/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/Soter/Client.php @@ -21,6 +21,10 @@ use EasyWeChat\Kernel\BaseClient; class Client extends BaseClient { /** + * @param string $openid + * @param string $json + * @param string $signature + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/SubscribeMessage/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/SubscribeMessage/Client.php index 02b3de984..a9a7dfeb0 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/SubscribeMessage/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/SubscribeMessage/Client.php @@ -40,6 +40,8 @@ class Client extends BaseClient /** * Send a template message. * + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -56,6 +58,8 @@ class Client extends BaseClient } /** + * @param array $data + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -74,7 +78,7 @@ class Client extends BaseClient foreach ($params['data'] as $key => $value) { if (is_array($value)) { - if (\array_key_exists('value', $value)) { + if (isset($value['value'])) { $params['data'][$key] = ['value' => $value['value']]; continue; @@ -109,6 +113,10 @@ class Client extends BaseClient /** * Combine templates and add them to your personal template library under your account. * + * @param string $tid + * @param array $kidList + * @param string|null $sceneDesc + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -125,6 +133,8 @@ class Client extends BaseClient /** * Delete personal template under account. * + * @param string $id + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -138,6 +148,8 @@ class Client extends BaseClient /** * Get keyword list under template title. * + * @param string $tid + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -151,6 +163,10 @@ class Client extends BaseClient /** * Get the title of the public template under the category to which the account belongs. * + * @param array $ids + * @param int $start + * @param int $limit + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/TemplateMessage/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/TemplateMessage/Client.php index 6c6da311f..08f8a3bec 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/TemplateMessage/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/TemplateMessage/Client.php @@ -20,7 +20,7 @@ use EasyWeChat\OfficialAccount\TemplateMessage\Client as BaseClient; */ class Client extends BaseClient { - public const API_SEND = 'cgi-bin/message/wxopen/template/send'; + const API_SEND = 'cgi-bin/message/wxopen/template/send'; /** * {@inheritdoc}. @@ -40,6 +40,9 @@ class Client extends BaseClient protected $required = ['touser', 'template_id', 'form_id']; /** + * @param int $offset + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -51,6 +54,8 @@ class Client extends BaseClient } /** + * @param string $id + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -62,6 +67,9 @@ class Client extends BaseClient } /** + * @param string $id + * @param array $keyword + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -76,6 +84,8 @@ class Client extends BaseClient } /** + * @param string $templateId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -89,6 +99,9 @@ class Client extends BaseClient } /** + * @param int $offset + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/MiniProgram/UniformMessage/Client.php b/src/vendor/overtrue/wechat/src/MiniProgram/UniformMessage/Client.php index 56a9132fb..6acb13e95 100644 --- a/src/vendor/overtrue/wechat/src/MiniProgram/UniformMessage/Client.php +++ b/src/vendor/overtrue/wechat/src/MiniProgram/UniformMessage/Client.php @@ -16,7 +16,7 @@ use EasyWeChat\OfficialAccount\TemplateMessage\Client as BaseClient; class Client extends BaseClient { - public const API_SEND = 'cgi-bin/message/wxopen/template/uniform_send'; + const API_SEND = 'cgi-bin/message/wxopen/template/uniform_send'; /** * {@inheritdoc}. @@ -61,6 +61,8 @@ class Client extends BaseClient protected $required = ['touser', 'template_id', 'form_id', 'miniprogram', 'appid']; /** + * @param array $data + * * @return array * * @throws InvalidArgumentException @@ -85,6 +87,8 @@ class Client extends BaseClient } /** + * @param array $data + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -99,6 +103,8 @@ class Client extends BaseClient } /** + * @param array $data + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Application.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Application.php index 75cb1ddf9..745363f3b 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Application.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Application.php @@ -29,7 +29,6 @@ use EasyWeChat\Kernel\ServiceContainer; * @property \EasyWeChat\OfficialAccount\User\TagClient $user_tag * @property \EasyWeChat\OfficialAccount\Menu\Client $menu * @property \EasyWeChat\OfficialAccount\TemplateMessage\Client $template_message - * @property \EasyWeChat\OfficialAccount\SubscribeMessage\Client $subscribe_message * @property \EasyWeChat\OfficialAccount\Material\Client $material * @property \EasyWeChat\OfficialAccount\CustomerService\Client $customer_service * @property \EasyWeChat\OfficialAccount\CustomerService\SessionClient $customer_service_session @@ -51,7 +50,6 @@ use EasyWeChat\Kernel\ServiceContainer; * @property \EasyWeChat\OfficialAccount\WiFi\CardClient $wifi_card * @property \EasyWeChat\OfficialAccount\WiFi\DeviceClient $wifi_device * @property \EasyWeChat\OfficialAccount\WiFi\ShopClient $wifi_shop - * @property \EasyWeChat\OfficialAccount\Guide\Client $guide */ class Application extends ServiceContainer { @@ -65,7 +63,6 @@ class Application extends ServiceContainer OAuth\ServiceProvider::class, Menu\ServiceProvider::class, TemplateMessage\ServiceProvider::class, - SubscribeMessage\ServiceProvider::class, Material\ServiceProvider::class, CustomerService\ServiceProvider::class, Semantic\ServiceProvider::class, @@ -87,7 +84,5 @@ class Application extends ServiceContainer BasicService\Media\ServiceProvider::class, BasicService\Url\ServiceProvider::class, BasicService\Jssdk\ServiceProvider::class, - // Append Guide Interface - Guide\ServiceProvider::class, ]; } diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Auth/AccessToken.php index 9d6e24455..aca1aca95 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Auth/AccessToken.php @@ -25,6 +25,9 @@ class AccessToken extends BaseAccessToken */ protected $endpointToGetToken = 'https://api.weixin.qq.com/cgi-bin/token'; + /** + * @return array + */ protected function getCredentials(): array { return [ diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Base/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Base/Client.php index 3d2a3e93c..ce8abc592 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Base/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Base/Client.php @@ -53,6 +53,9 @@ class Client extends BaseClient /** * Check the callback address network. * + * @param string $action + * @param string $operator + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/Client.php index 27515c3d7..6c2eee1d3 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/Client.php @@ -34,12 +34,14 @@ use EasyWeChat\Kernel\Support\Arr; */ class Client extends BaseClient { - public const PREVIEW_BY_OPENID = 'touser'; - public const PREVIEW_BY_NAME = 'towxname'; + const PREVIEW_BY_OPENID = 'touser'; + const PREVIEW_BY_NAME = 'towxname'; /** * Send a message. * + * @param array $message + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -60,6 +62,8 @@ class Client extends BaseClient /** * Preview a message. * + * @param array $message + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -73,6 +77,9 @@ class Client extends BaseClient /** * Delete a broadcast. * + * @param string $msgId + * @param int $index + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -91,6 +98,8 @@ class Client extends BaseClient /** * Get a broadcast status. * + * @param string $msgId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -108,7 +117,9 @@ class Client extends BaseClient /** * Send a text message. * - * @param mixed $reception + * @param string $message + * @param mixed $reception + * @param array $attributes * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -123,7 +134,9 @@ class Client extends BaseClient /** * Send a news message. * - * @param mixed $reception + * @param string $mediaId + * @param mixed $reception + * @param array $attributes * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @@ -138,7 +151,9 @@ class Client extends BaseClient /** * Send a voice message. * - * @param mixed $reception + * @param string $mediaId + * @param mixed $reception + * @param array $attributes * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @@ -153,7 +168,9 @@ class Client extends BaseClient /** * Send a image message. * - * @param mixed $reception + * @param string $mediaId + * @param mixed $reception + * @param array $attributes * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -168,7 +185,9 @@ class Client extends BaseClient /** * Send a video message. * - * @param mixed $reception + * @param string $mediaId + * @param mixed $reception + * @param array $attributes * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @@ -183,7 +202,9 @@ class Client extends BaseClient /** * Send a card message. * - * @param mixed $reception + * @param string $cardId + * @param mixed $reception + * @param array $attributes * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -298,7 +319,9 @@ class Client extends BaseClient } /** - * @param string $method + * @param \EasyWeChat\Kernel\Contracts\MessageInterface $message + * @param string $reception + * @param string $method * * @return mixed * @@ -313,8 +336,9 @@ class Client extends BaseClient } /** - * @param mixed $reception - * @param array $attributes + * @param \EasyWeChat\Kernel\Contracts\MessageInterface $message + * @param mixed $reception + * @param array $attributes * * @return mixed * diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/MessageBuilder.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/MessageBuilder.php index 9bf80f103..70465b068 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/MessageBuilder.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Broadcasting/MessageBuilder.php @@ -39,6 +39,8 @@ class MessageBuilder /** * Set message. * + * @param \EasyWeChat\Kernel\Contracts\MessageInterface $message + * * @return $this */ public function message(MessageInterface $message) @@ -51,6 +53,8 @@ class MessageBuilder /** * Set target user or group. * + * @param array $to + * * @return $this */ public function to(array $to) @@ -61,6 +65,8 @@ class MessageBuilder } /** + * @param int $tagId + * * @return \EasyWeChat\OfficialAccount\Broadcasting\MessageBuilder */ public function toTag(int $tagId) @@ -76,6 +82,8 @@ class MessageBuilder } /** + * @param array $openids + * * @return \EasyWeChat\OfficialAccount\Broadcasting\MessageBuilder */ public function toUsers(array $openids) @@ -100,6 +108,8 @@ class MessageBuilder } /** + * @param array $attributes + * * @return \EasyWeChat\OfficialAccount\Broadcasting\MessageBuilder */ public function with(array $attributes) @@ -112,6 +122,10 @@ class MessageBuilder /** * Build message. * + * @param array $prepends + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function build(array $prepends = []): array @@ -134,6 +148,11 @@ class MessageBuilder /** * Build preview message. * + * @param string $by + * @param string $user + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function buildForPreview(string $by, string $user): array diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/BoardingPassClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/BoardingPassClient.php index de332984d..b1575abdd 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/BoardingPassClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/BoardingPassClient.php @@ -19,6 +19,8 @@ namespace EasyWeChat\OfficialAccount\Card; class BoardingPassClient extends Client { /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/Client.php index 9db4e1bf6..5737d52e5 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/Client.php @@ -70,6 +70,7 @@ class Client extends BaseClient * 创建卡券. * * @param string $cardType + * @param array $attributes * * @return mixed * @@ -135,6 +136,7 @@ class Client extends BaseClient * * @param string $cardId * @param string $type + * @param array $attributes * * @return mixed * @@ -172,6 +174,8 @@ class Client extends BaseClient /** * 创建二维码. * + * @param array $cards + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -291,6 +295,8 @@ class Client extends BaseClient /** * 设置测试白名单(by username). * + * @param array $usernames + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CodeClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CodeClient.php index 8a000a313..dcf96da45 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CodeClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CodeClient.php @@ -23,6 +23,9 @@ class CodeClient extends BaseClient /** * 导入code接口. * + * @param string $cardId + * @param array $codes + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +44,8 @@ class CodeClient extends BaseClient /** * 查询导入code数目. * + * @param string $cardId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -58,6 +63,9 @@ class CodeClient extends BaseClient /** * 核查code接口. * + * @param string $cardId + * @param array $codes + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -76,6 +84,10 @@ class CodeClient extends BaseClient /** * 查询 Code 接口. * + * @param string $code + * @param string $cardId + * @param bool $checkConsume + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -95,6 +107,10 @@ class CodeClient extends BaseClient /** * 更改Code接口. * + * @param string $code + * @param string $newCode + * @param string $cardId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -114,6 +130,9 @@ class CodeClient extends BaseClient /** * 设置卡券失效. * + * @param string $code + * @param string $cardId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -132,6 +151,9 @@ class CodeClient extends BaseClient /** * 核销 Code 接口. * + * @param string $code + * @param string|null $cardId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -153,6 +175,8 @@ class CodeClient extends BaseClient /** * Code解码接口. * + * @param string $encryptedCode + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CoinClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CoinClient.php index ceb93c58c..b99d841da 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CoinClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/CoinClient.php @@ -31,6 +31,9 @@ class CoinClient extends BaseClient } /** + * @param string $cardId + * @param int $quantity + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -55,6 +58,8 @@ class CoinClient extends BaseClient } /** + * @param int $count + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -68,6 +73,8 @@ class CoinClient extends BaseClient } /** + * @param string $orderId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -79,6 +86,8 @@ class CoinClient extends BaseClient } /** + * @param array $filters + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -90,6 +99,10 @@ class CoinClient extends BaseClient } /** + * @param string $cardId + * @param string $orderId + * @param int $quantity + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GeneralCardClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GeneralCardClient.php index 5f52e17dc..1505981af 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GeneralCardClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GeneralCardClient.php @@ -21,6 +21,8 @@ class GeneralCardClient extends Client /** * 通用卡接口激活. * + * @param array $info + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -34,6 +36,9 @@ class GeneralCardClient extends Client /** * 通用卡撤销激活. * + * @param string $cardId + * @param string $code + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -52,6 +57,8 @@ class GeneralCardClient extends Client /** * 更新会员信息. * + * @param array $params + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardClient.php index 938f8c982..d8779d022 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardClient.php @@ -23,6 +23,8 @@ class GiftCardClient extends BaseClient /** * 申请微信支付礼品卡权限接口. * + * @param string $subMchId + * * @return mixed */ public function add(string $subMchId) @@ -37,6 +39,9 @@ class GiftCardClient extends BaseClient /** * 绑定商户号到礼品卡小程序接口(商户号必须为公众号申请的商户号,否则报错). * + * @param string $subMchId + * @param string $wxaAppid + * * @return mixed */ public function bind(string $subMchId, string $wxaAppid) @@ -52,6 +57,9 @@ class GiftCardClient extends BaseClient /** * 上传小程序代码. * + * @param string $wxaAppid + * @param string $pageId + * * @return mixed */ public function set(string $wxaAppid, string $pageId) diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardOrderClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardOrderClient.php index 9f3be735e..b4e1b157d 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardOrderClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardOrderClient.php @@ -23,6 +23,8 @@ class GiftCardOrderClient extends BaseClient /** * 查询-单个礼品卡订单信息接口. * + * @param string $orderId + * * @return mixed */ public function get(string $orderId) @@ -37,6 +39,12 @@ class GiftCardOrderClient extends BaseClient /** * 查询-批量查询礼品卡订单信息接口. * + * @param int $beginTime + * @param int $endTime + * @param int $offset + * @param int $count + * @param string $sortType + * * @return mixed */ public function list(int $beginTime, int $endTime, int $offset = 0, int $count = 10, string $sortType = 'ASC') @@ -55,6 +63,8 @@ class GiftCardOrderClient extends BaseClient /** * 退款接口. * + * @param string $orderId + * * @return mixed */ public function refund(string $orderId) diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardPageClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardPageClient.php index c525ec621..bf36109e8 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardPageClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/GiftCardPageClient.php @@ -23,6 +23,8 @@ class GiftCardPageClient extends BaseClient /** * 创建-礼品卡货架接口. * + * @param array $attributes + * * @return mixed */ public function add(array $attributes) @@ -37,6 +39,8 @@ class GiftCardPageClient extends BaseClient /** * 查询-礼品卡货架信息接口. * + * @param string $pageId + * * @return mixed */ public function get(string $pageId) @@ -51,6 +55,10 @@ class GiftCardPageClient extends BaseClient /** * 修改-礼品卡货架信息接口. * + * @param string $pageId + * @param string $bannerPicUrl + * @param array $themeList + * * @return mixed */ public function update(string $pageId, string $bannerPicUrl, array $themeList) @@ -79,6 +87,8 @@ class GiftCardPageClient extends BaseClient /** * 下架-礼品卡货架接口(下架某一个货架或者全部货架). * + * @param string $pageId + * * @return mixed */ public function setMaintain(string $pageId = '') diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/InvoiceClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/InvoiceClient.php index d80d3bbba..127b3af13 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/InvoiceClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/InvoiceClient.php @@ -23,6 +23,9 @@ class InvoiceClient extends BaseClient /** * 设置支付后开票信息接口. * + * @param string $mchid + * @param string $sPappid + * * @return mixed */ public function set(string $mchid, string $sPappid) @@ -50,6 +53,9 @@ class InvoiceClient extends BaseClient /** * 设置授权页字段信息接口. * + * @param array $userData + * @param array $bizData + * * @return mixed */ public function setAuthField(array $userData, array $bizData) @@ -77,6 +83,9 @@ class InvoiceClient extends BaseClient /** * 查询开票信息. * + * @param string $orderId + * @param string $appId + * * @return mixed */ public function getAuthData(string $appId, string $orderId) @@ -90,6 +99,9 @@ class InvoiceClient extends BaseClient } /** + * @param string $action + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/JssdkClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/JssdkClient.php index 76307241e..9a6bb51a2 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/JssdkClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/JssdkClient.php @@ -23,6 +23,11 @@ use function EasyWeChat\Kernel\Support\str_random; class JssdkClient extends Jssdk { /** + * @param bool $refresh + * @param string $type + * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException @@ -36,6 +41,8 @@ class JssdkClient extends Jssdk /** * 微信卡券:JSAPI 卡券发放. * + * @param array $cards + * * @return string */ public function assign(array $cards) @@ -49,6 +56,7 @@ class JssdkClient extends Jssdk * 生成 js添加到卡包 需要的 card_list 项. * * @param string $cardId + * @param array $extension * * @return array * diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MeetingTicketClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MeetingTicketClient.php index ae0cff7c4..892c5ad99 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MeetingTicketClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MeetingTicketClient.php @@ -19,6 +19,8 @@ namespace EasyWeChat\OfficialAccount\Card; class MeetingTicketClient extends Client { /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MemberCardClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MemberCardClient.php index f2a975815..41d051ceb 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MemberCardClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MemberCardClient.php @@ -21,6 +21,8 @@ class MemberCardClient extends Client /** * 会员卡接口激活. * + * @param array $info + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -34,6 +36,9 @@ class MemberCardClient extends Client /** * 设置开卡字段接口. * + * @param string $cardId + * @param array $settings + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -49,6 +54,9 @@ class MemberCardClient extends Client /** * 拉取会员信息接口. * + * @param string $cardId + * @param string $code + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -67,6 +75,8 @@ class MemberCardClient extends Client /** * 更新会员信息. * + * @param array $params + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MovieTicketClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MovieTicketClient.php index 9540a740c..e6d90365b 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MovieTicketClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/MovieTicketClient.php @@ -19,6 +19,8 @@ namespace EasyWeChat\OfficialAccount\Card; class MovieTicketClient extends Client { /** + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/SubMerchantClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/SubMerchantClient.php index cf09c810c..f0584920d 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Card/SubMerchantClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Card/SubMerchantClient.php @@ -24,6 +24,8 @@ class SubMerchantClient extends BaseClient /** * 添加子商户. * + * @param array $info + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -51,6 +53,9 @@ class SubMerchantClient extends BaseClient /** * 更新子商户. * + * @param int $merchantId + * @param array $info + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,8 +64,7 @@ class SubMerchantClient extends BaseClient public function update(int $merchantId, array $info = []) { $params = [ - 'info' => array_merge( - ['merchant_id' => $merchantId], + 'info' => array_merge(['merchant_id' => $merchantId], Arr::only($info, [ 'brand_name', 'logo_url', @@ -71,8 +75,7 @@ class SubMerchantClient extends BaseClient 'agreement_media_id', 'operator_media_id', 'app_id', - ]) - ), + ])), ]; return $this->httpPostJson('card/submerchant/update', $params); @@ -81,6 +84,8 @@ class SubMerchantClient extends BaseClient /** * 获取子商户信息. * + * @param int $merchantId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -94,6 +99,10 @@ class SubMerchantClient extends BaseClient /** * 批量获取子商户信息. * + * @param int $beginId + * @param int $limit + * @param string $status + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Comment/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Comment/Client.php index 6a5da109e..4f45b741c 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Comment/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Comment/Client.php @@ -23,6 +23,9 @@ class Client extends BaseClient /** * Open article comment. * + * @param string $msgId + * @param int|null $index + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +44,9 @@ class Client extends BaseClient /** * Close comment. * + * @param string $msgId + * @param int|null $index + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +65,12 @@ class Client extends BaseClient /** * Get article comments. * + * @param string $msgId + * @param int $index + * @param int $begin + * @param int $count + * @param int $type + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -80,6 +92,10 @@ class Client extends BaseClient /** * Mark elect comment. * + * @param string $msgId + * @param int $index + * @param int $commentId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -99,6 +115,10 @@ class Client extends BaseClient /** * Unmark elect comment. * + * @param string $msgId + * @param int $index + * @param int $commentId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -118,6 +138,10 @@ class Client extends BaseClient /** * Delete comment. * + * @param string $msgId + * @param int $index + * @param int $commentId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -137,6 +161,11 @@ class Client extends BaseClient /** * Reply to a comment. * + * @param string $msgId + * @param int $index + * @param int $commentId + * @param string $content + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -157,6 +186,10 @@ class Client extends BaseClient /** * Delete a reply. * + * @param string $msgId + * @param int $index + * @param int $commentId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Client.php index 772691047..64e43e522 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Client.php @@ -47,6 +47,9 @@ class Client extends BaseClient /** * Create a staff. * + * @param string $account + * @param string $nickname + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -65,6 +68,9 @@ class Client extends BaseClient /** * Update a staff. * + * @param string $account + * @param string $nickname + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -83,6 +89,8 @@ class Client extends BaseClient /** * Delete a staff. * + * @param string $account + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -96,6 +104,9 @@ class Client extends BaseClient /** * Invite a staff. * + * @param string $account + * @param string $wechatId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -114,6 +125,9 @@ class Client extends BaseClient /** * Set staff avatar. * + * @param string $account + * @param string $path + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -141,6 +155,8 @@ class Client extends BaseClient /** * Send a message. * + * @param array $message + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -154,6 +170,8 @@ class Client extends BaseClient /** * Show typing status. * + * @param string $openid + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -170,6 +188,8 @@ class Client extends BaseClient /** * Hide typing status. * + * @param string $openid + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -188,6 +208,8 @@ class Client extends BaseClient * * @param int $startTime * @param int $endTime + * @param int $msgId + * @param int $number * * @return mixed * diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Messenger.php b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Messenger.php index 4b66a9e6b..69bf2f36f 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Messenger.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/Messenger.php @@ -82,6 +82,8 @@ class Messenger /** * Set staff account to send message. * + * @param string $account + * * @return Messenger */ public function by(string $account) @@ -92,6 +94,8 @@ class Messenger } /** + * @param string $account + * * @return Messenger */ public function from(string $account) @@ -146,6 +150,8 @@ class Messenger /** * Return property. * + * @param string $property + * * @return mixed */ public function __get(string $property) diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/SessionClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/SessionClient.php index 0802b328d..b92b6db18 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/SessionClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/CustomerService/SessionClient.php @@ -23,6 +23,8 @@ class SessionClient extends BaseClient /** * List all sessions of $account. * + * @param string $account + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -47,6 +49,9 @@ class SessionClient extends BaseClient /** * Create a session. * + * @param string $account + * @param string $openid + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -65,6 +70,9 @@ class SessionClient extends BaseClient /** * Close a session. * + * @param string $account + * @param string $openid + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -83,6 +91,8 @@ class SessionClient extends BaseClient /** * Get a session. * + * @param string $openid + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/DataCube/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/DataCube/Client.php index ca530249a..0bf1c2142 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/DataCube/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/DataCube/Client.php @@ -23,6 +23,9 @@ class Client extends BaseClient /** * 获取用户增减数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userSummary(string $from, string $to) @@ -33,6 +36,9 @@ class Client extends BaseClient /** * 获取累计用户数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userCumulate(string $from, string $to) @@ -43,6 +49,9 @@ class Client extends BaseClient /** * 获取图文群发每日数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function articleSummary(string $from, string $to) @@ -53,6 +62,9 @@ class Client extends BaseClient /** * 获取图文群发总数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function articleTotal(string $from, string $to) @@ -63,6 +75,9 @@ class Client extends BaseClient /** * 获取图文统计数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userReadSummary(string $from, string $to) @@ -73,6 +88,9 @@ class Client extends BaseClient /** * 获取图文统计分时数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userReadHourly(string $from, string $to) @@ -83,6 +101,9 @@ class Client extends BaseClient /** * 获取图文分享转发数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userShareSummary(string $from, string $to) @@ -93,6 +114,9 @@ class Client extends BaseClient /** * 获取图文分享转发分时数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function userShareHourly(string $from, string $to) @@ -103,6 +127,9 @@ class Client extends BaseClient /** * 获取消息发送概况数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageSummary(string $from, string $to) @@ -113,6 +140,9 @@ class Client extends BaseClient /** * 获取消息分送分时数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageHourly(string $from, string $to) @@ -123,6 +153,9 @@ class Client extends BaseClient /** * 获取消息发送周数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageWeekly(string $from, string $to) @@ -133,6 +166,9 @@ class Client extends BaseClient /** * 获取消息发送月数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageMonthly(string $from, string $to) @@ -143,6 +179,9 @@ class Client extends BaseClient /** * 获取消息发送分布数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageDistSummary(string $from, string $to) @@ -153,6 +192,9 @@ class Client extends BaseClient /** * 获取消息发送分布周数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageDistWeekly(string $from, string $to) @@ -163,6 +205,9 @@ class Client extends BaseClient /** * 获取消息发送分布月数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function upstreamMessageDistMonthly(string $from, string $to) @@ -173,6 +218,9 @@ class Client extends BaseClient /** * 获取接口分析数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function interfaceSummary(string $from, string $to) @@ -183,6 +231,9 @@ class Client extends BaseClient /** * 获取接口分析分时数据. * + * @param string $from + * @param string $to + * * @return mixed */ public function interfaceSummaryHourly(string $from, string $to) @@ -193,7 +244,9 @@ class Client extends BaseClient /** * 拉取卡券概况数据接口. * - * @param int $condSource + * @param string $from + * @param string $to + * @param int $condSource * * @return mixed */ @@ -209,6 +262,11 @@ class Client extends BaseClient /** * 获取免费券数据接口. * + * @param string $from + * @param string $to + * @param int $condSource + * @param string $cardId + * * @return mixed */ public function freeCardSummary(string $from, string $to, int $condSource = 0, string $cardId = '') @@ -224,7 +282,9 @@ class Client extends BaseClient /** * 拉取会员卡数据接口. * - * @param int $condSource + * @param string $from + * @param string $to + * @param int $condSource * * @return mixed */ @@ -240,6 +300,10 @@ class Client extends BaseClient /** * 拉取单张会员卡数据接口. * + * @param string $from + * @param string $to + * @param string $cardId + * * @return mixed */ public function memberCardSummaryById(string $from, string $to, string $cardId) @@ -254,6 +318,11 @@ class Client extends BaseClient /** * 查询数据. * + * @param string $api + * @param string $from + * @param string $to + * @param array $ext + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Device/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Device/Client.php index 7d2bbfc93..8dc9d739e 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Device/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Device/Client.php @@ -23,6 +23,10 @@ use EasyWeChat\Kernel\BaseClient; class Client extends BaseClient { /** + * @param string $deviceId + * @param string $openid + * @param string $content + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -43,6 +47,8 @@ class Client extends BaseClient /** * Get device qrcode. * + * @param array $deviceIds + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +65,10 @@ class Client extends BaseClient } /** + * @param array $devices + * @param string $productId + * @param int $opType + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -79,6 +89,8 @@ class Client extends BaseClient /** * 获取 device id 和二维码 * + * @param string $productId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -93,6 +105,10 @@ class Client extends BaseClient } /** + * @param string $openid + * @param string $deviceId + * @param string $ticket + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -110,6 +126,10 @@ class Client extends BaseClient } /** + * @param string $openid + * @param string $deviceId + * @param string $ticket + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -127,6 +147,9 @@ class Client extends BaseClient } /** + * @param string $openid + * @param string $deviceId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -143,6 +166,9 @@ class Client extends BaseClient } /** + * @param string $openid + * @param string $deviceId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -159,6 +185,8 @@ class Client extends BaseClient } /** + * @param string $deviceId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -173,6 +201,8 @@ class Client extends BaseClient } /** + * @param string $ticket + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -187,6 +217,8 @@ class Client extends BaseClient } /** + * @param string $deviceId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -202,6 +234,8 @@ class Client extends BaseClient } /** + * @param string $openid + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Goods/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Goods/Client.php index 49c7ec299..c720e3187 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Goods/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Goods/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Add the goods. * + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -38,6 +40,8 @@ class Client extends BaseClient /** * Update the goods. * + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -53,6 +57,8 @@ class Client extends BaseClient /** * Get add or update goods results. * + * @param string $ticket + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -68,6 +74,8 @@ class Client extends BaseClient /** * Get goods information. * + * @param string $pid + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -85,6 +93,10 @@ class Client extends BaseClient /** * Get a list of goods. * + * @param string $context + * @param int $page + * @param int $size + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Material/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Material/Client.php index ef39ab689..a62fded49 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Material/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Material/Client.php @@ -33,6 +33,8 @@ class Client extends BaseClient /** * Upload image. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -47,6 +49,8 @@ class Client extends BaseClient /** * Upload voice. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -61,6 +65,8 @@ class Client extends BaseClient /** * Upload thumb. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -75,6 +81,10 @@ class Client extends BaseClient /** * Upload video. * + * @param string $path + * @param string $title + * @param string $description + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -88,9 +98,7 @@ class Client extends BaseClient [ 'title' => $title, 'introduction' => $description, - ], - JSON_UNESCAPED_UNICODE - ), + ], JSON_UNESCAPED_UNICODE), ]; return $this->upload('video', $path, $params); @@ -126,7 +134,9 @@ class Client extends BaseClient /** * Update article. * + * @param string $mediaId * @param array|Article $article + * @param int $index * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -151,6 +161,8 @@ class Client extends BaseClient /** * Upload image for article. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -164,6 +176,8 @@ class Client extends BaseClient /** * Fetch material. * + * @param string $mediaId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -183,6 +197,8 @@ class Client extends BaseClient /** * Delete material by media ID. * + * @param string $mediaId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -210,6 +226,10 @@ class Client extends BaseClient * ] * } * + * @param string $type + * @param int $offset + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -241,6 +261,10 @@ class Client extends BaseClient /** * Upload material. * + * @param string $type + * @param string $path + * @param array $form + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -261,6 +285,8 @@ class Client extends BaseClient /** * Get API by type. * + * @param string $type + * * @return string */ public function getApiByType(string $type) diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Menu/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Menu/Client.php index c8b3b8898..9c132c629 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Menu/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Menu/Client.php @@ -47,6 +47,9 @@ class Client extends BaseClient /** * Add menu. * + * @param array $buttons + * @param array $matchRule + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -86,6 +89,8 @@ class Client extends BaseClient /** * Test conditional menu. * + * @param string $userId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/OCR/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/OCR/Client.php index 80b7a95e0..6aa44bcbf 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/OCR/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/OCR/Client.php @@ -31,6 +31,9 @@ class Client extends BaseClient /** * ID card OCR. * + * @param string $path + * @param string $type + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -42,7 +45,7 @@ class Client extends BaseClient throw new InvalidArgumentException(sprintf("Unsupported type: '%s'", $type)); } - return $this->httpPost('cv/ocr/idcard', [ + return $this->httpGet('cv/ocr/idcard', [ 'type' => $type, 'img_url' => $path, ]); @@ -51,13 +54,15 @@ class Client extends BaseClient /** * Bank card OCR. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException */ public function bankCard(string $path) { - return $this->httpPost('cv/ocr/bankcard', [ + return $this->httpGet('cv/ocr/bankcard', [ 'img_url' => $path, ]); } @@ -65,13 +70,15 @@ class Client extends BaseClient /** * Vehicle license OCR. * + * @param string $path + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException */ public function vehicleLicense(string $path) { - return $this->httpPost('cv/ocr/drivinglicense', [ + return $this->httpGet('cv/ocr/driving', [ 'img_url' => $path, ]); } diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/POI/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/POI/Client.php index f71d5d293..6a8e57060 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/POI/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/POI/Client.php @@ -35,6 +35,8 @@ class Client extends BaseClient /** * Get POI by ID. * + * @param int $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -48,6 +50,9 @@ class Client extends BaseClient /** * List POI. * + * @param int $offset + * @param int $limit + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -66,6 +71,8 @@ class Client extends BaseClient /** * Create a POI. * + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -83,6 +90,8 @@ class Client extends BaseClient } /** + * @param array $databaseInfo + * * @return int * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -100,6 +109,9 @@ class Client extends BaseClient /** * Update a POI. * + * @param int $poiId + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -119,6 +131,8 @@ class Client extends BaseClient /** * Delete a POI. * + * @param int $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Semantic/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Semantic/Client.php index d0e2a51df..e83792ff6 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Semantic/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Semantic/Client.php @@ -23,6 +23,10 @@ class Client extends BaseClient /** * Get the semantic content of giving string. * + * @param string $keyword + * @param string $categories + * @param array $optional + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Guard.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Guard.php index a42205f35..c72384737 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Guard.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Guard.php @@ -20,6 +20,9 @@ use EasyWeChat\Kernel\ServerGuard; */ class Guard extends ServerGuard { + /** + * @return bool + */ protected function shouldReturnRawResponse(): bool { return !is_null($this->app['request']->get('echostr')); diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Handlers/EchoStrHandler.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Handlers/EchoStrHandler.php index b99937577..f076abf53 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Handlers/EchoStrHandler.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Server/Handlers/EchoStrHandler.php @@ -29,6 +29,8 @@ class EchoStrHandler implements EventHandlerInterface /** * EchoStrHandler constructor. + * + * @param ServiceContainer $app */ public function __construct(ServiceContainer $app) { diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/Client.php index bcc2a0dbb..c4010089c 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/Client.php @@ -48,6 +48,9 @@ class Client extends BaseClient /** * Get shake info. * + * @param string $ticket + * @param bool $needPoi + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -67,6 +70,8 @@ class Client extends BaseClient } /** + * @param string $ticket + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string */ public function userWithPoi(string $ticket) diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/DeviceClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/DeviceClient.php index 0e0f7d704..859a1209a 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/DeviceClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/DeviceClient.php @@ -21,6 +21,8 @@ use EasyWeChat\Kernel\BaseClient; class DeviceClient extends BaseClient { /** + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -34,6 +36,8 @@ class DeviceClient extends BaseClient /** * Get audit status. * + * @param int $applyId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -51,6 +55,9 @@ class DeviceClient extends BaseClient /** * Update a device comment. * + * @param array $deviceIdentifier + * @param string $comment + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -69,6 +76,9 @@ class DeviceClient extends BaseClient /** * Bind location for device. * + * @param array $deviceIdentifier + * @param int $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -85,6 +95,10 @@ class DeviceClient extends BaseClient } /** + * @param array $deviceIdentifier + * @param int $poiId + * @param string $appId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -105,6 +119,8 @@ class DeviceClient extends BaseClient /** * Fetch batch of devices by deviceIds. * + * @param array $deviceIdentifiers + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function listByIds(array $deviceIdentifiers) @@ -120,6 +136,9 @@ class DeviceClient extends BaseClient /** * Pagination to get batch of devices. * + * @param int $lastId + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function list(int $lastId, int $count) @@ -136,6 +155,10 @@ class DeviceClient extends BaseClient /** * Fetch batch of devices by applyId. * + * @param int $applyId + * @param int $lastId + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string */ public function listByApplyId(int $applyId, int $lastId, int $count) @@ -153,6 +176,8 @@ class DeviceClient extends BaseClient /** * Fetch batch of devices. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/GroupClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/GroupClient.php index 1907c2d06..9fd578d29 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/GroupClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/GroupClient.php @@ -23,6 +23,8 @@ class GroupClient extends BaseClient /** * Add device group. * + * @param string $name + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -40,6 +42,9 @@ class GroupClient extends BaseClient /** * Update a device group name. * + * @param int $groupId + * @param string $name + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -58,6 +63,8 @@ class GroupClient extends BaseClient /** * Delete device group. * + * @param int $groupId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -75,6 +82,9 @@ class GroupClient extends BaseClient /** * List all device groups. * + * @param int $begin + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -93,6 +103,10 @@ class GroupClient extends BaseClient /** * Get detail of a device group. * + * @param int $groupId + * @param int $begin + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -112,6 +126,9 @@ class GroupClient extends BaseClient /** * Add one or more devices to a device group. * + * @param int $groupId + * @param array $deviceIdentifiers + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -130,6 +147,9 @@ class GroupClient extends BaseClient /** * Remove one or more devices from a device group. * + * @param int $groupId + * @param array $deviceIdentifiers + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/MaterialClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/MaterialClient.php index e7a4d06e4..edc40b28b 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/MaterialClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/MaterialClient.php @@ -24,6 +24,9 @@ class MaterialClient extends BaseClient /** * Upload image material. * + * @param string $path + * @param string $type + * * @return string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/PageClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/PageClient.php index e230bb3d3..73ba1acd9 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/PageClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/PageClient.php @@ -21,6 +21,8 @@ use EasyWeChat\Kernel\BaseClient; class PageClient extends BaseClient { /** + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -32,6 +34,9 @@ class PageClient extends BaseClient } /** + * @param int $pageId + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -45,6 +50,8 @@ class PageClient extends BaseClient /** * Fetch batch of pages by pageIds. * + * @param array $pageIds + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -63,6 +70,9 @@ class PageClient extends BaseClient /** * Pagination to get batch of pages. * + * @param int $begin + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -82,6 +92,8 @@ class PageClient extends BaseClient /** * delete a page. * + * @param int $pageId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/RelationClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/RelationClient.php index 774199bdf..de80911ed 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/RelationClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/RelationClient.php @@ -23,6 +23,9 @@ class RelationClient extends BaseClient /** * Bind pages for device. * + * @param array $deviceIdentifier + * @param array $pageIds + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +44,8 @@ class RelationClient extends BaseClient /** * Get pageIds by deviceId. * + * @param array $deviceIdentifier + * * @return array|\EasyWeChat\Kernel\Support\Collection * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +64,10 @@ class RelationClient extends BaseClient /** * Get devices by pageId. * + * @param int $pageId + * @param int $begin + * @param int $count + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/StatsClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/StatsClient.php index 1b52ef7fd..a4b55eb63 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/StatsClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/ShakeAround/StatsClient.php @@ -23,8 +23,9 @@ class StatsClient extends BaseClient /** * Fetch statistics data by deviceId. * - * @param int $beginTime (Unix timestamp) - * @param int $endTime (Unix timestamp) + * @param array $deviceIdentifier + * @param int $beginTime (Unix timestamp) + * @param int $endTime (Unix timestamp) * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -45,6 +46,9 @@ class StatsClient extends BaseClient /** * Fetch all devices statistics data by date. * + * @param int $timestamp + * @param int $pageIndex + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -63,6 +67,7 @@ class StatsClient extends BaseClient /** * Fetch statistics data by pageId. * + * @param int $pageId * @param int $beginTime (Unix timestamp) * @param int $endTime (Unix timestamp) * @@ -85,6 +90,9 @@ class StatsClient extends BaseClient /** * Fetch all pages statistics data by date. * + * @param int $timestamp + * @param int $pageIndex + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/Store/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/Store/Client.php index 5b2bab7ef..364309655 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/Store/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/Store/Client.php @@ -47,6 +47,9 @@ class Client extends BaseClient /** * Search store from tencent map. * + * @param int $districtId + * @param string $keyword + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -78,6 +81,8 @@ class Client extends BaseClient /** * Create a merchant. * + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -91,6 +96,8 @@ class Client extends BaseClient /** * Update a merchant. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -104,6 +111,8 @@ class Client extends BaseClient /** * Create a store from tencent map. * + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -117,6 +126,8 @@ class Client extends BaseClient /** * Create a store. * + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -130,6 +141,9 @@ class Client extends BaseClient /** * Update a store. * + * @param int $poiId + * @param array $baseInfo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -145,6 +159,8 @@ class Client extends BaseClient /** * Get store by ID. * + * @param int $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -158,6 +174,9 @@ class Client extends BaseClient /** * List store. * + * @param int $offset + * @param int $limit + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -176,6 +195,8 @@ class Client extends BaseClient /** * Delete a store. * + * @param int $poiId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/TemplateMessage/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/TemplateMessage/Client.php index 11f592d20..4853e7928 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/TemplateMessage/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/TemplateMessage/Client.php @@ -22,7 +22,7 @@ use ReflectionClass; */ class Client extends BaseClient { - public const API_SEND = 'cgi-bin/message/template/send'; + const API_SEND = 'cgi-bin/message/template/send'; /** * Attributes. @@ -42,7 +42,7 @@ class Client extends BaseClient * * @var array */ - protected $required = ['touser', 'template_id']; + protected $required = [ 'touser', 'template_id' ]; /** * Set industry. @@ -88,10 +88,12 @@ class Client extends BaseClient * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \GuzzleHttp\Exception\GuzzleException */ - public function addTemplate($shortId) + public function addTemplate($shortId, $keyword_name_list) { - $params = ['template_id_short' => $shortId]; - + $params = [ + 'template_id_short' => $shortId, // 模板库中模板的编号,有“TM**”和“OPENTMTM**”等形式,对于类目模板,为纯数字ID + 'keyword_name_list' => $keyword_name_list // 选用的类目模板的关键词,按顺序传入,如果为空,或者关键词不在模板库中,会返回40246错误码 + ]; return $this->httpPostJson('cgi-bin/template/api_add_template', $params); } @@ -120,7 +122,7 @@ class Client extends BaseClient */ public function deletePrivateTemplate($templateId) { - $params = ['template_id' => $templateId]; + $params = [ 'template_id' => $templateId ]; return $this->httpPostJson('cgi-bin/template/del_private_template', $params); } @@ -128,6 +130,8 @@ class Client extends BaseClient /** * Send a template message. * + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -146,6 +150,8 @@ class Client extends BaseClient /** * Send template-message for subscription. * + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -162,6 +168,8 @@ class Client extends BaseClient } /** + * @param array $data + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -171,19 +179,21 @@ class Client extends BaseClient $params = array_merge($this->message, $data); foreach ($params as $key => $value) { - if (in_array($key, $this->required, true) && empty($value) && empty($this->message[$key])) { + if (in_array($key, $this->required, true) && empty($value) && empty($this->message[ $key ])) { throw new InvalidArgumentException(sprintf('Attribute "%s" can not be empty!', $key)); } - $params[$key] = empty($value) ? $this->message[$key] : $value; + $params[ $key ] = empty($value) ? $this->message[ $key ] : $value; } - $params['data'] = $this->formatData($params['data'] ?? []); + $params[ 'data' ] = $this->formatData($params[ 'data' ] ?? []); return $params; } /** + * @param array $data + * * @return array */ protected function formatData(array $data) @@ -192,16 +202,16 @@ class Client extends BaseClient foreach ($data as $key => $value) { if (is_array($value)) { - if (\array_key_exists('value', $value)) { - $formatted[$key] = $value; + if (isset($value[ 'value' ])) { + $formatted[ $key ] = $value; continue; } if (count($value) >= 2) { $value = [ - 'value' => $value[0], - 'color' => $value[1], + 'value' => $value[ 0 ], + 'color' => $value[ 1 ], ]; } } else { @@ -210,7 +220,7 @@ class Client extends BaseClient ]; } - $formatted[$key] = $value; + $formatted[ $key ] = $value; } return $formatted; @@ -221,6 +231,6 @@ class Client extends BaseClient */ protected function restoreMessage() { - $this->message = (new ReflectionClass(static::class))->getDefaultProperties()['message']; + $this->message = ( new ReflectionClass(static::class) )->getDefaultProperties()[ 'message' ]; } } diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/User/TagClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/User/TagClient.php index 9c145c8a7..d41e36372 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/User/TagClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/User/TagClient.php @@ -23,6 +23,8 @@ class TagClient extends BaseClient /** * Create tag. * + * @param string $name + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -52,6 +54,9 @@ class TagClient extends BaseClient /** * Update a tag name. * + * @param int $tagId + * @param string $name + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -72,6 +77,8 @@ class TagClient extends BaseClient /** * Delete tag. * + * @param int $tagId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -89,6 +96,8 @@ class TagClient extends BaseClient /** * Get user tags. * + * @param string $openid + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -104,6 +113,9 @@ class TagClient extends BaseClient /** * Get users from a tag. * + * @param int $tagId + * @param string $nextOpenId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -122,6 +134,9 @@ class TagClient extends BaseClient /** * Batch tag users. * + * @param array $openids + * @param int $tagId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -140,6 +155,9 @@ class TagClient extends BaseClient /** * Untag users from a tag. * + * @param array $openids + * @param int $tagId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/User/UserClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/User/UserClient.php index 625ae0f2f..6b9491f7e 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/User/UserClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/User/UserClient.php @@ -23,6 +23,9 @@ class UserClient extends BaseClient /** * Fetch a user by open id. * + * @param string $openid + * @param string $lang + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -40,6 +43,9 @@ class UserClient extends BaseClient /** * Batch get users. * + * @param array $openids + * @param string $lang + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -76,6 +82,9 @@ class UserClient extends BaseClient /** * Set user remark. * + * @param string $openid + * @param string $remark + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -94,6 +103,8 @@ class UserClient extends BaseClient /** * Get black list. * + * @param string|null $beginOpenid + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -141,6 +152,9 @@ class UserClient extends BaseClient } /** + * @param string $oldAppId + * @param array $openidList + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/CardClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/CardClient.php index 9e58b0d63..76a4e6a13 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/CardClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/CardClient.php @@ -23,6 +23,8 @@ class CardClient extends BaseClient /** * Set shop card coupon delivery information. * + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,8 @@ class CardClient extends BaseClient /** * Get shop card coupon delivery information. * + * @param int $shopId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/Client.php b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/Client.php index 638a8c932..076957d37 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/Client.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/Client.php @@ -23,6 +23,10 @@ class Client extends BaseClient /** * Get Wi-Fi statistics. * + * @param string $beginDate + * @param string $endDate + * @param int $shopId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +46,10 @@ class Client extends BaseClient /** * Get the material QR code. * + * @param int $shopId + * @param string $ssid + * @param int $type + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -61,6 +69,8 @@ class Client extends BaseClient /** * Wi-Fi completion page jump applet. * + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -74,6 +84,8 @@ class Client extends BaseClient /** * Set the top banner jump applet. * + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/DeviceClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/DeviceClient.php index 99ff8fdea..8fecbf78c 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/DeviceClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/DeviceClient.php @@ -23,6 +23,10 @@ class DeviceClient extends BaseClient /** * Add a password device. * + * @param int $shopId + * @param string $ssid + * @param string $password + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +46,10 @@ class DeviceClient extends BaseClient /** * Add a portal device. * + * @param int $shopId + * @param string $ssid + * @param bool $reset + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -61,6 +69,8 @@ class DeviceClient extends BaseClient /** * Delete device by MAC address. * + * @param string $macAddress + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -74,6 +84,9 @@ class DeviceClient extends BaseClient /** * Get a list of devices. * + * @param int $page + * @param int $size + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -92,6 +105,10 @@ class DeviceClient extends BaseClient /** * Get a list of devices by shop ID. * + * @param int $shopId + * @param int $page + * @param int $size + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/ShopClient.php b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/ShopClient.php index 30cac2111..34f1c975b 100644 --- a/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/ShopClient.php +++ b/src/vendor/overtrue/wechat/src/OfficialAccount/WiFi/ShopClient.php @@ -23,6 +23,8 @@ class ShopClient extends BaseClient /** * Get shop Wi-Fi information. * + * @param int $shopId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,9 @@ class ShopClient extends BaseClient /** * Get a list of Wi-Fi shops. * + * @param int $page + * @param int $size + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -54,6 +59,9 @@ class ShopClient extends BaseClient /** * Update shop Wi-Fi information. * + * @param int $shopId + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -69,6 +77,9 @@ class ShopClient extends BaseClient /** * Clear shop network and equipment. * + * @param int $shopId + * @param string|null $ssid + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Application.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Application.php index 79faa4d93..459bb96c9 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Application.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Application.php @@ -12,7 +12,6 @@ namespace EasyWeChat\OpenPlatform; use EasyWeChat\Kernel\ServiceContainer; -use EasyWeChat\Kernel\Traits\ResponseCastable; use EasyWeChat\MiniProgram\Encryptor; use EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken; use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application as MiniProgram; @@ -22,8 +21,6 @@ use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application as OfficialAc use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\OAuth\ComponentDelegate; use EasyWeChat\OpenPlatform\Authorizer\Server\Guard; -use function EasyWeChat\Kernel\data_get; - /** * Class Application. * @@ -41,8 +38,6 @@ use function EasyWeChat\Kernel\data_get; */ class Application extends ServiceContainer { - use ResponseCastable; - /** * @var array */ @@ -66,6 +61,12 @@ class Application extends ServiceContainer /** * Creates the officialAccount application. + * + * @param string $appId + * @param string|null $refreshToken + * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken + * + * @return \EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application */ public function officialAccount(string $appId, string $refreshToken = null, AccessToken $accessToken = null): OfficialAccount { @@ -87,6 +88,12 @@ class Application extends ServiceContainer /** * Creates the miniProgram application. + * + * @param string $appId + * @param string|null $refreshToken + * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken + * + * @return \EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application */ public function miniProgram(string $appId, string $refreshToken = null, AccessToken $accessToken = null): MiniProgram { @@ -104,7 +111,10 @@ class Application extends ServiceContainer /** * Return the pre-authorization login page url. * + * @param string $callbackUrl * @param string|array|null $optional + * + * @return string */ public function getPreAuthorizationUrl(string $callbackUrl, $optional = []): string { @@ -114,7 +124,7 @@ class Application extends ServiceContainer 'pre_auth_code' => $optional, ]; } else { - $optional['pre_auth_code'] = data_get($this->createPreAuthorizationCode(), 'pre_auth_code'); + $optional['pre_auth_code'] = $this->createPreAuthorizationCode()['pre_auth_code']; } $queries = \array_merge($optional, [ @@ -128,10 +138,10 @@ class Application extends ServiceContainer /** * Return the pre-authorization login page url (mobile). * - * @param string|array|null $optional + * @param string $callbackUrl + * @param string|array|null $optional * * @return string - * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function getMobilePreAuthorizationUrl(string $callbackUrl, $optional = []): string { @@ -141,7 +151,7 @@ class Application extends ServiceContainer 'pre_auth_code' => $optional, ]; } else { - $optional['pre_auth_code'] = data_get($this->createPreAuthorizationCode(), 'pre_auth_code'); + $optional['pre_auth_code'] = $this->createPreAuthorizationCode()['pre_auth_code']; } $queries = \array_merge($optional, [ @@ -154,6 +164,12 @@ class Application extends ServiceContainer return 'https://mp.weixin.qq.com/safe/bindcomponent?'.http_build_query($queries).'#wechat_redirect'; } + /** + * @param string $appId + * @param string|null $refreshToken + * + * @return array + */ protected function getAuthorizerConfig(string $appId, string $refreshToken = null): array { return $this['config']->merge([ @@ -163,6 +179,11 @@ class Application extends ServiceContainer ])->toArray(); } + /** + * @param \EasyWeChat\OpenPlatform\Authorizer\Auth\AccessToken|null $accessToken + * + * @return array + */ protected function getReplaceServices(AccessToken $accessToken = null): array { $services = [ diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/AccessToken.php index a8cf5e428..c15d78da6 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/AccessToken.php @@ -35,6 +35,9 @@ class AccessToken extends BaseAccessToken */ protected $endpointToGetToken = 'cgi-bin/component/api_component_token'; + /** + * @return array + */ protected function getCredentials(): array { return [ diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/VerifyTicket.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/VerifyTicket.php index d2c495acf..9ad04c7de 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/VerifyTicket.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Auth/VerifyTicket.php @@ -31,6 +31,8 @@ class VerifyTicket /** * Constructor. + * + * @param \EasyWeChat\OpenPlatform\Application $app */ public function __construct(Application $app) { @@ -40,6 +42,8 @@ class VerifyTicket /** * Put the credential `component_verify_ticket` in cache. * + * @param string $ticket + * * @return $this * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -60,6 +64,8 @@ class VerifyTicket /** * Get the credential `component_verify_ticket` from cache. * + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException * @throws \Psr\SimpleCache\InvalidArgumentException @@ -75,6 +81,8 @@ class VerifyTicket /** * Get cache key. + * + * @return string */ protected function getCacheKey(): string { diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/Auth/AccessToken.php index 2c9d53c08..07b808c09 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/Auth/AccessToken.php @@ -44,6 +44,9 @@ class AccessToken extends BaseAccessToken /** * AuthorizerAccessToken constructor. + * + * @param \Pimple\Container $app + * @param \EasyWeChat\OpenPlatform\Application $component */ public function __construct(Container $app, Application $component) { @@ -64,6 +67,9 @@ class AccessToken extends BaseAccessToken ]; } + /** + * @return string + */ public function getEndpoint(): string { return 'cgi-bin/component/api_authorizer_token?'.http_build_query([ diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Account/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Account/Client.php index f1b7afb16..c23772d08 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Account/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Account/Client.php @@ -32,10 +32,10 @@ class Client extends BaseClient * 修改头像. * * @param string $mediaId 头像素材mediaId - * @param string $left 剪裁框左上角x坐标(取值范围:[0, 1]) - * @param string $top 剪裁框左上角y坐标(取值范围:[0, 1]) - * @param string $right 剪裁框右下角x坐标(取值范围:[0, 1]) - * @param string $bottom 剪裁框右下角y坐标(取值范围:[0, 1]) + * @param float $left 剪裁框左上角x坐标(取值范围:[0, 1]) + * @param float $top 剪裁框左上角y坐标(取值范围:[0, 1]) + * @param float $right 剪裁框右下角x坐标(取值范围:[0, 1]) + * @param float $bottom 剪裁框右下角y坐标(取值范围:[0, 1]) * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @@ -44,17 +44,14 @@ class Client extends BaseClient */ public function updateAvatar( string $mediaId, - $left = '0.0', - $top = '0.0', - $right = '1.0', - $bottom = '1.0' + float $left = 0.0, + float $top = 0.0, + float $right = 1.0, + float $bottom = 1.0 ) { $params = [ 'head_img_media_id' => $mediaId, - 'x1' => \strval($left), - 'y1' => \strval($top), - 'x2' => \strval($right), - 'y2' => \strval($bottom), + 'x1' => $left, 'y1' => $top, 'x2' => $right, 'y2' => $bottom, ]; return $this->httpPostJson('cgi-bin/account/modifyheadimage', $params); diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Application.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Application.php index 85bb55793..b4b8c135a 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Application.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Application.php @@ -29,6 +29,9 @@ class Application extends MiniProgram { /** * Application constructor. + * + * @param array $config + * @param array $prepends */ public function __construct(array $config = [], array $prepends = []) { diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Auth/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Auth/Client.php index caf87d74e..05bb704d8 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Auth/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Auth/Client.php @@ -29,6 +29,9 @@ class Client extends BaseClient /** * Client constructor. + * + * @param \EasyWeChat\Kernel\ServiceContainer $app + * @param \EasyWeChat\OpenPlatform\Application $component */ public function __construct(ServiceContainer $app, Application $component) { @@ -40,6 +43,8 @@ class Client extends BaseClient /** * Get session info by code. * + * @param string $code + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Code/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Code/Client.php index c733f6a53..700e76a16 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Code/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Code/Client.php @@ -21,6 +21,11 @@ use EasyWeChat\Kernel\BaseClient; class Client extends BaseClient { /** + * @param int $templateId + * @param string $extJson + * @param string $version + * @param string $description + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -37,6 +42,8 @@ class Client extends BaseClient } /** + * @param string|null $path + * * @return \EasyWeChat\Kernel\Http\Response * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -70,25 +77,27 @@ class Client extends BaseClient } /** + * @param array $itemList + * @param string|null $feedbackInfo + * @param string|null $feedbackStuff + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \GuzzleHttp\Exception\GuzzleException */ - public function submitAudit(array $data, string $feedbackInfo = null, string $feedbackStuff = null) + public function submitAudit(array $itemList, string $feedbackInfo = null, string $feedbackStuff = null) { - if (isset($data['item_list'])) { - return $this->httpPostJson('wxa/submit_audit', $data); - } - return $this->httpPostJson('wxa/submit_audit', [ - 'item_list' => $data, + 'item_list' => $itemList, 'feedback_info' => $feedbackInfo, 'feedback_stuff' => $feedbackStuff, ]); } /** + * @param int $auditId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -143,6 +152,8 @@ class Client extends BaseClient } /** + * @param string $action + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -158,6 +169,8 @@ class Client extends BaseClient /** * 分阶段发布. * + * @param int $grayPercentage + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -210,6 +223,8 @@ class Client extends BaseClient /** * 设置最低基础库版本. * + * @param string $version + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Domain/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Domain/Client.php index c065802ed..2a6547c3b 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Domain/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Domain/Client.php @@ -21,6 +21,8 @@ use EasyWeChat\Kernel\BaseClient; class Client extends BaseClient { /** + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -34,6 +36,7 @@ class Client extends BaseClient /** * 设置小程序业务域名. * + * @param array $domains * @param string $action * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Setting/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Setting/Client.php index 3186fda3c..77be09976 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Setting/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Setting/Client.php @@ -150,9 +150,7 @@ class Client extends BaseClient $params = ['nick_name' => $nickname]; return $this->httpPostJson( - 'cgi-bin/wxverify/checkwxverifynickname', - $params - ); + 'cgi-bin/wxverify/checkwxverifynickname', $params); } /** @@ -232,6 +230,9 @@ class Client extends BaseClient /** * 获取可以用来设置的公众号列表. * + * @param int $page + * @param int $num + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Tester/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Tester/Client.php index 6ff090190..011c93344 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Tester/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/MiniProgram/Tester/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * 绑定小程序体验者. * + * @param string $wechatId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -38,6 +40,8 @@ class Client extends BaseClient /** * 解绑小程序体验者. * + * @param string $wechatId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -53,6 +57,7 @@ class Client extends BaseClient /** * 获取体验者列表. * + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Account/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Account/Client.php index 603bc3d04..9e7b38b8a 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Account/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Account/Client.php @@ -29,6 +29,9 @@ class Client extends BaseClient /** * Client constructor. + * + * @param \EasyWeChat\Kernel\ServiceContainer $app + * @param \EasyWeChat\OpenPlatform\Application $component */ public function __construct(ServiceContainer $app, Application $component) { @@ -39,6 +42,11 @@ class Client extends BaseClient /** * 从第三方平台跳转至微信公众平台授权注册页面, 授权注册小程序. + * + * @param string $callbackUrl + * @param bool $copyWxVerify + * + * @return string */ public function getFastRegistrationUrl(string $callbackUrl, bool $copyWxVerify = true): string { @@ -55,6 +63,8 @@ class Client extends BaseClient /** * 小程序快速注册. * + * @param string $ticket + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Application.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Application.php index 9e2377859..08509d248 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Application.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/Application.php @@ -26,6 +26,9 @@ class Application extends OfficialAccount { /** * Application constructor. + * + * @param array $config + * @param array $prepends */ public function __construct(array $config = [], array $prepends = []) { diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/MiniProgram/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/MiniProgram/Client.php index e5d4e1f97..d32b51bfe 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/MiniProgram/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/MiniProgram/Client.php @@ -36,6 +36,10 @@ class Client extends BaseClient /** * 关联小程序. * + * @param string $appId + * @param bool $notifyUsers + * @param bool $showProfile + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -55,6 +59,8 @@ class Client extends BaseClient /** * 解除已关联的小程序. * + * @param string $appId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/OAuth/ComponentDelegate.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/OAuth/ComponentDelegate.php index 4a1cab2be..a79d177b6 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/OAuth/ComponentDelegate.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Authorizer/OfficialAccount/OAuth/ComponentDelegate.php @@ -28,6 +28,8 @@ class ComponentDelegate implements WeChatComponentInterface /** * ComponentDelegate Constructor. + * + * @param \EasyWeChat\OpenPlatform\Application $app */ public function __construct(Application $app) { diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Base/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Base/Client.php index 57baa65b2..ec78a5fd9 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Base/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Base/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Get authorization info. * + * @param string|null $authCode + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +43,8 @@ class Client extends BaseClient /** * Get authorizer info. * + * @param string $appId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +63,9 @@ class Client extends BaseClient /** * Get options. * + * @param string $appId + * @param string $name + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -78,6 +85,10 @@ class Client extends BaseClient /** * Set authorizer option. * + * @param string $appId + * @param string $name + * @param string $value + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/CodeTemplate/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/CodeTemplate/Client.php index 5949eb0a3..2929cb68f 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/CodeTemplate/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/CodeTemplate/Client.php @@ -36,6 +36,8 @@ class Client extends BaseClient /** * 将草稿箱的草稿选为小程序代码模版. * + * @param int $draftId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Component/Client.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Component/Client.php index b7d140284..eafb3f5b8 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Component/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Component/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * 通过法人微信快速创建小程序. * + * @param array $params + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,10 @@ class Client extends BaseClient /** * 查询创建任务状态. * + * @param string $companyName + * @param string $legalPersonaWechat + * @param string $legalPersonaName + * * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Guard.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Guard.php index ca0f1d265..ee306ab19 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Guard.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Guard.php @@ -11,13 +11,13 @@ namespace EasyWeChat\OpenPlatform\Server; +use function EasyWeChat\Kernel\data_get; use EasyWeChat\Kernel\ServerGuard; use EasyWeChat\OpenPlatform\Server\Handlers\Authorized; use EasyWeChat\OpenPlatform\Server\Handlers\Unauthorized; use EasyWeChat\OpenPlatform\Server\Handlers\UpdateAuthorized; use EasyWeChat\OpenPlatform\Server\Handlers\VerifyTicketRefreshed; use Symfony\Component\HttpFoundation\Response; -use function EasyWeChat\Kernel\data_get; /** * Class Guard. @@ -26,13 +26,15 @@ use function EasyWeChat\Kernel\data_get; */ class Guard extends ServerGuard { - public const EVENT_AUTHORIZED = 'authorized'; - public const EVENT_UNAUTHORIZED = 'unauthorized'; - public const EVENT_UPDATE_AUTHORIZED = 'updateauthorized'; - public const EVENT_COMPONENT_VERIFY_TICKET = 'component_verify_ticket'; - public const EVENT_THIRD_FAST_REGISTERED = 'notify_third_fasteregister'; + const EVENT_AUTHORIZED = 'authorized'; + const EVENT_UNAUTHORIZED = 'unauthorized'; + const EVENT_UPDATE_AUTHORIZED = 'updateauthorized'; + const EVENT_COMPONENT_VERIFY_TICKET = 'component_verify_ticket'; + const EVENT_THIRD_FAST_REGISTERED = 'notify_third_fasteregister'; /** + * @return \Symfony\Component\HttpFoundation\Response + * * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Handlers/VerifyTicketRefreshed.php b/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Handlers/VerifyTicketRefreshed.php index 67fe661f7..e5ce58d5a 100644 --- a/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Handlers/VerifyTicketRefreshed.php +++ b/src/vendor/overtrue/wechat/src/OpenPlatform/Server/Handlers/VerifyTicketRefreshed.php @@ -14,8 +14,6 @@ namespace EasyWeChat\OpenPlatform\Server\Handlers; use EasyWeChat\Kernel\Contracts\EventHandlerInterface; use EasyWeChat\OpenPlatform\Application; -use function EasyWeChat\Kernel\data_get; - /** * Class VerifyTicketRefreshed. * @@ -30,6 +28,8 @@ class VerifyTicketRefreshed implements EventHandlerInterface /** * Constructor. + * + * @param \EasyWeChat\OpenPlatform\Application $app */ public function __construct(Application $app) { @@ -41,10 +41,8 @@ class VerifyTicketRefreshed implements EventHandlerInterface */ public function handle($payload = null) { - $ticket = data_get($payload, 'ComponentVerifyTicket'); - - if (!empty($ticket)) { - $this->app['verify_ticket']->setTicket($ticket); + if (!empty($payload['ComponentVerifyTicket'])) { + $this->app['verify_ticket']->setTicket($payload['ComponentVerifyTicket']); } } } diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Application.php b/src/vendor/overtrue/wechat/src/OpenWork/Application.php index 47db6da09..bde14214f 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Application.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Application.php @@ -53,6 +53,8 @@ class Application extends ServiceContainer /** * Creates the miniProgram application. + * + * @return \EasyWeChat\Work\MiniProgram\Application */ public function miniProgram(): \EasyWeChat\Work\MiniProgram\Application { @@ -62,6 +64,8 @@ class Application extends ServiceContainer /** * @param string $authCorpId 企业 corp_id * @param string $permanentCode 企业永久授权码 + * + * @return Work */ public function work(string $authCorpId, string $permanentCode): Work { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/OpenWork/Auth/AccessToken.php index a90ab32e8..3f00a254f 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Auth/AccessToken.php @@ -39,6 +39,8 @@ class AccessToken extends BaseAccessToken /** * Credential for get token. + * + * @return array */ protected function getCredentials(): array { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Corp/Client.php b/src/vendor/overtrue/wechat/src/OpenWork/Corp/Client.php index 122077947..689f573fd 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Corp/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Corp/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * Client constructor. * 三方接口有三个access_token,这里用的是suite_access_token. + * + * @param \EasyWeChat\Kernel\ServiceContainer $app */ public function __construct(ServiceContainer $app) { @@ -35,6 +37,7 @@ class Client extends BaseClient * * @param string $preAuthCode 预授权码 * @param string $redirectUri 回调地址 + * @param string $state * * @return string * @@ -72,6 +75,9 @@ class Client extends BaseClient * 设置授权配置. * 该接口可对某次授权进行配置. * + * @param string $preAuthCode + * @param array $sessionInfo + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -109,6 +115,9 @@ class Client extends BaseClient /** * 获取企业授权信息. * + * @param string $authCorpId + * @param string $permanentCode + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -127,6 +136,9 @@ class Client extends BaseClient /** * 获取应用的管理员列表. * + * @param string $authCorpId + * @param string $agentId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -145,6 +157,10 @@ class Client extends BaseClient /** * 获取登录url. * + * @param string $redirectUri + * @param string $scope + * @param string|null $state + * * @return string */ public function getOAuthRedirectUrl(string $redirectUri = '', string $scope = 'snsapi_userinfo', string $state = null) @@ -165,6 +181,8 @@ class Client extends BaseClient /** * 第三方根据code获取企业成员信息. * + * @param string $code + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -181,6 +199,8 @@ class Client extends BaseClient /** * 第三方使用user_ticket获取成员详情. * + * @param string $userTicket + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Corp/ServiceProvider.php b/src/vendor/overtrue/wechat/src/OpenWork/Corp/ServiceProvider.php index f467e182b..0cc8ea9aa 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Corp/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Corp/ServiceProvider.php @@ -26,6 +26,8 @@ class ServiceProvider implements ServiceProviderInterface * * This method should only be used to configure services and parameters. * It should not get services. + * + * @param \Pimple\Container $app */ public function register(Container $app) { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/MiniProgram/Client.php b/src/vendor/overtrue/wechat/src/OpenWork/MiniProgram/Client.php index a054aae02..29dae19ac 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/MiniProgram/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/MiniProgram/Client.php @@ -21,6 +21,8 @@ class Client extends BaseClient { /** * Client constructor. + * + * @param \EasyWeChat\Kernel\ServiceContainer $app */ public function __construct(ServiceContainer $app) { @@ -30,6 +32,8 @@ class Client extends BaseClient /** * Get session info by code. * + * @param string $code + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Provider/Client.php b/src/vendor/overtrue/wechat/src/OpenWork/Provider/Client.php index 047ac0e15..690d98802 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Provider/Client.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Provider/Client.php @@ -23,6 +23,9 @@ class Client extends BaseClient { /** * Client constructor. + * + * + * @param ServiceContainer $app */ public function __construct(ServiceContainer $app) { @@ -32,6 +35,10 @@ class Client extends BaseClient /** * 单点登录 - 获取登录的地址. * + * @param string $redirectUri + * @param string $userType + * @param string $state + * * @return string */ public function getLoginUrl(string $redirectUri = '', string $userType = 'admin', string $state = '') @@ -51,6 +58,8 @@ class Client extends BaseClient /** * 单点登录 - 获取登录用户信息. * + * @param string $authCode + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -68,6 +77,8 @@ class Client extends BaseClient /** * 获取注册定制化URL. * + * @param string $registerCode + * * @return string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -91,6 +102,11 @@ class Client extends BaseClient /** * 获取注册码. * + * @param string $corpName + * @param string $adminName + * @param string $adminMobile + * @param string $state + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -117,6 +133,8 @@ class Client extends BaseClient * * Desc:该API用于查询企业注册状态,企业注册成功返回注册信息. * + * @param string $registerCode + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -140,6 +158,12 @@ class Client extends BaseClient * 该接口只能使用注册完成回调事件或者查询注册状态返回的access_token。 * 调用设置通讯录同步完成后或者access_token超过30分钟失效(即解除通讯录锁定状态)则不能继续调用该接口。 * + * @param string $accessToken + * @param string $agentId + * @param array $allowUser + * @param array $allowParty + * @param array $allowTag + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -167,6 +191,8 @@ class Client extends BaseClient * * Desc:该API用于设置通讯录同步完成,解除通讯录锁定状态,同时使通讯录迁移access_token失效。 * + * @param string $accessToken + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -177,38 +203,4 @@ class Client extends BaseClient return $this->httpGet('cgi-bin/sync/contact_sync_success', $params); } - - /** - * 通讯录单个搜索 - * - * @param string $queryWord - * @param $agentId - * @param int $offset - * @param int $limit - * @param int $queryType - * @param null $fullMatchField - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function searchContact( - string $queryWord, - $agentId, - int $offset = 0, - int $limit = 50, - int $queryType = 0, - $fullMatchField = null - ) { - $params = []; - $params['auth_corpid'] = $this->app['config']['corp_id']; - $params['query_word'] = $queryWord; - $params['query_type'] = $queryType; - $params['agentid'] = $agentId; - $params['offset'] = $offset; - $params['limit'] = $limit; - !empty($fullMatchField) && $params['full_match_field'] = $fullMatchField; - - return $this->httpPostJson('cgi-bin/service/contact/search', $params); - } } diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Provider/ServiceProvider.php b/src/vendor/overtrue/wechat/src/OpenWork/Provider/ServiceProvider.php index 09c4faa9f..2185fec64 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Provider/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Provider/ServiceProvider.php @@ -23,6 +23,9 @@ class ServiceProvider implements ServiceProviderInterface { protected $app; + /** + * @param Container $app + */ public function register(Container $app) { $this->app = $app; diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Server/Guard.php b/src/vendor/overtrue/wechat/src/OpenWork/Server/Guard.php index 1e16794f2..5700a774b 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Server/Guard.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Server/Guard.php @@ -34,6 +34,9 @@ class Guard extends ServerGuard return $this; } + /** + * @return bool + */ protected function shouldReturnRawResponse(): bool { return !is_null($this->app['request']->get('echostr')); @@ -45,6 +48,8 @@ class Guard extends ServerGuard } /** + * @param array $message + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Server/Handlers/EchoStrHandler.php b/src/vendor/overtrue/wechat/src/OpenWork/Server/Handlers/EchoStrHandler.php index b63af19b3..78af70188 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Server/Handlers/EchoStrHandler.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Server/Handlers/EchoStrHandler.php @@ -29,6 +29,8 @@ class EchoStrHandler implements EventHandlerInterface /** * EchoStrHandler constructor. + * + * @param ServiceContainer $app */ public function __construct(ServiceContainer $app) { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/AccessToken.php b/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/AccessToken.php index 3c5a6111b..e4e248d79 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/AccessToken.php @@ -42,6 +42,8 @@ class AccessToken extends BaseAccessToken /** * Credential for get token. + * + * @return array */ protected function getCredentials(): array { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/SuiteTicket.php b/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/SuiteTicket.php index c9acb7dc2..4c01710b5 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/SuiteTicket.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/SuiteAuth/SuiteTicket.php @@ -31,6 +31,8 @@ class SuiteTicket /** * SuiteTicket constructor. + * + * @param Application $app */ public function __construct(Application $app) { @@ -38,6 +40,8 @@ class SuiteTicket } /** + * @param string $ticket + * * @return $this * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -56,6 +60,8 @@ class SuiteTicket } /** + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException * @throws \Psr\SimpleCache\InvalidArgumentException @@ -69,6 +75,9 @@ class SuiteTicket throw new RuntimeException('Credential "suite_ticket" does not exist in cache.'); } + /** + * @return string + */ protected function getCacheKey(): string { return 'easywechat.open_work.suite_ticket.'.$this->app['config']['suite_id']; diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Work/Application.php b/src/vendor/overtrue/wechat/src/OpenWork/Work/Application.php index fbf9cc2d8..676013dd0 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Work/Application.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Work/Application.php @@ -24,6 +24,11 @@ class Application extends Work { /** * Application constructor. + * + * @param string $authCorpId + * @param string $permanentCode + * @param OpenWork $component + * @param array $prepends */ public function __construct(string $authCorpId, string $permanentCode, OpenWork $component, array $prepends = []) { diff --git a/src/vendor/overtrue/wechat/src/OpenWork/Work/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/OpenWork/Work/Auth/AccessToken.php index 6a895a723..e80758a09 100644 --- a/src/vendor/overtrue/wechat/src/OpenWork/Work/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/OpenWork/Work/Auth/AccessToken.php @@ -41,6 +41,11 @@ class AccessToken extends BaseAccessToken /** * AccessToken constructor. + * + * @param Container $app + * @param string $authCorpId + * @param string $permanentCode + * @param Application $component */ public function __construct(Container $app, string $authCorpId, string $permanentCode, Application $component) { @@ -52,6 +57,8 @@ class AccessToken extends BaseAccessToken /** * Credential for get token. + * + * @return array */ protected function getCredentials(): array { @@ -61,6 +68,9 @@ class AccessToken extends BaseAccessToken ]; } + /** + * @return string + */ public function getEndpoint(): string { return 'cgi-bin/service/get_corp_token?'.http_build_query([ diff --git a/src/vendor/overtrue/wechat/src/Payment/Application.php b/src/vendor/overtrue/wechat/src/Payment/Application.php index 5f5b4c628..79873e2bc 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Application.php +++ b/src/vendor/overtrue/wechat/src/Payment/Application.php @@ -20,7 +20,7 @@ use EasyWeChat\OfficialAccount; /** * Class Application. - * + * @property \EasyWeChat\Payment\Base\Client $base * @property \EasyWeChat\Payment\Bill\Client $bill * @property \EasyWeChat\Payment\Fundflow\Client $fundflow * @property \EasyWeChat\Payment\Jssdk\Client $jssdk @@ -75,6 +75,10 @@ class Application extends ServiceContainer /** * Build payment scheme for product. + * + * @param string $productId + * + * @return string */ public function scheme(string $productId): string { @@ -92,6 +96,8 @@ class Application extends ServiceContainer } /** + * @param string $codeUrl + * * @return string */ public function codeUrlScheme(string $codeUrl) @@ -100,6 +106,8 @@ class Application extends ServiceContainer } /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @codeCoverageIgnore @@ -112,6 +120,8 @@ class Application extends ServiceContainer } /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @codeCoverageIgnore @@ -124,6 +134,8 @@ class Application extends ServiceContainer } /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @codeCoverageIgnore @@ -138,6 +150,9 @@ class Application extends ServiceContainer /** * Set sub-merchant. * + * @param string $mchId + * @param string|null $appId + * * @return $this */ public function setSubMerchant(string $mchId, string $appId = null) @@ -148,12 +163,17 @@ class Application extends ServiceContainer return $this; } + /** + * @return bool + */ public function inSandbox(): bool { return (bool) $this['config']->get('sandbox'); } /** + * @param string|null $endpoint + * * @return string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Base/Client.php b/src/vendor/overtrue/wechat/src/Payment/Base/Client.php index 1fbb6075e..75d4c9a1f 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Base/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Base/Client.php @@ -18,6 +18,8 @@ class Client extends BaseClient /** * Pay the order. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -34,6 +36,8 @@ class Client extends BaseClient /** * Get openid by auth code. * + * @param string $authCode + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Bill/Client.php b/src/vendor/overtrue/wechat/src/Payment/Bill/Client.php index e8df7f9a5..20a9b6301 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Bill/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Bill/Client.php @@ -19,6 +19,10 @@ class Client extends BaseClient /** * Download bill history as a table file. * + * @param string $date + * @param string $type + * @param array $optional + * * @return \EasyWeChat\Kernel\Http\StreamResponse|\Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Contract/Client.php b/src/vendor/overtrue/wechat/src/Payment/Contract/Client.php index 141d22cfb..695c65806 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Contract/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Contract/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * entrust official account. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -39,6 +41,8 @@ class Client extends BaseClient /** * entrust app. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -55,6 +59,8 @@ class Client extends BaseClient /** * entrust html 5. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -71,6 +77,8 @@ class Client extends BaseClient /** * apply papay. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -81,12 +89,14 @@ class Client extends BaseClient { $params['appid'] = $this->app['config']->app_id; - return $this->safeRequest('pay/pappayapply', $params); + return $this->safeRequest('papay/pappayapply', $params); } /** * delete papay contrace. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Coupon/Client.php b/src/vendor/overtrue/wechat/src/Payment/Coupon/Client.php index b81831b18..101a42b77 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Coupon/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Coupon/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * send a cash coupon. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -40,6 +42,8 @@ class Client extends BaseClient /** * query a coupon stock. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -56,6 +60,8 @@ class Client extends BaseClient /** * query a info of coupon. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Fundflow/Client.php b/src/vendor/overtrue/wechat/src/Payment/Fundflow/Client.php index b69c7ebbb..359d4f3e4 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Fundflow/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Fundflow/Client.php @@ -19,7 +19,9 @@ class Client extends BaseClient /** * Download fundflow history as a table file. * - * @param array $options + * @param string $date + * @param string $type + * @param array $options * * @return array|\EasyWeChat\Kernel\Http\Response|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * diff --git a/src/vendor/overtrue/wechat/src/Payment/Jssdk/Client.php b/src/vendor/overtrue/wechat/src/Payment/Jssdk/Client.php index 52cf7f71a..37dc9d4b4 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Jssdk/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Jssdk/Client.php @@ -32,6 +32,9 @@ class Client extends JssdkClient * ); * * + * @param string $prepayId + * @param bool $json + * * @return string|array */ public function bridgeConfig(string $prepayId, bool $json = true) @@ -55,6 +58,10 @@ class Client extends JssdkClient *

      * wx.chooseWXPay({...});
      * 
+ * + * @param string $prepayId + * + * @return array */ public function sdkConfig(string $prepayId): array { @@ -68,6 +75,10 @@ class Client extends JssdkClient /** * Generate app payment parameters. + * + * @param string $prepayId + * + * @return array */ public function appConfig(string $prepayId): array { @@ -89,6 +100,7 @@ class Client extends JssdkClient * Generate js config for share user address. * * @param string|\Overtrue\Socialite\AccessTokenInterface $accessToken + * @param bool $json * * @return string|array */ @@ -123,6 +135,10 @@ class Client extends JssdkClient /** * Generate js config for contract of mini program. + * + * @param array $params + * + * @return array */ public function contractConfig(array $params): array { diff --git a/src/vendor/overtrue/wechat/src/Payment/Kernel/BaseClient.php b/src/vendor/overtrue/wechat/src/Payment/Kernel/BaseClient.php index c765f4044..74f3939f3 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Kernel/BaseClient.php +++ b/src/vendor/overtrue/wechat/src/Payment/Kernel/BaseClient.php @@ -34,6 +34,8 @@ class BaseClient /** * Constructor. + * + * @param \EasyWeChat\Payment\Application $app */ public function __construct(Application $app) { @@ -55,7 +57,10 @@ class BaseClient /** * Make a API request. * + * @param string $endpoint + * @param array $params * @param string $method + * @param array $options * @param bool $returnResponse * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string @@ -107,7 +112,10 @@ class BaseClient /** * Make a request and return raw response. * + * @param string $endpoint + * @param array $params * @param string $method + * @param array $options * * @return ResponseInterface * @@ -126,7 +134,12 @@ class BaseClient /** * Make a request and return an array. * + * @param string $endpoint + * @param array $params * @param string $method + * @param array $options + * + * @return array * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -143,7 +156,9 @@ class BaseClient * Request with SSL. * * @param string $endpoint + * @param array $params * @param string $method + * @param array $options * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -163,6 +178,10 @@ class BaseClient /** * Wrapping an API endpoint. + * + * @param string $endpoint + * + * @return string */ protected function wrap(string $endpoint): string { diff --git a/src/vendor/overtrue/wechat/src/Payment/Merchant/Client.php b/src/vendor/overtrue/wechat/src/Payment/Merchant/Client.php index 493bce13b..f31a7e281 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Merchant/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Merchant/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Add sub-merchant. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -35,6 +37,8 @@ class Client extends BaseClient /** * Query sub-merchant by merchant id. * + * @param string $id + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -51,6 +55,8 @@ class Client extends BaseClient /** * Query sub-merchant by wechat id. * + * @param string $id + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -65,6 +71,9 @@ class Client extends BaseClient } /** + * @param array $params + * @param array $query + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Notify/Handler.php b/src/vendor/overtrue/wechat/src/Payment/Notify/Handler.php index 886e55f9b..c657433a9 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Notify/Handler.php +++ b/src/vendor/overtrue/wechat/src/Payment/Notify/Handler.php @@ -20,8 +20,8 @@ use Symfony\Component\HttpFoundation\Response; abstract class Handler { - public const SUCCESS = 'SUCCESS'; - public const FAIL = 'FAIL'; + const SUCCESS = 'SUCCESS'; + const FAIL = 'FAIL'; /** * @var \EasyWeChat\Payment\Application @@ -69,16 +69,24 @@ abstract class Handler /** * Handle incoming notify. * + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response */ abstract public function handle(Closure $closure); + /** + * @param string $message + */ public function fail(string $message) { $this->fail = $message; } /** + * @param array $attributes + * @param bool $sign + * * @return $this */ public function respondWith(array $attributes, bool $sign = false) @@ -92,6 +100,8 @@ abstract class Handler /** * Build xml and return the response to WeChat. * + * @return \Symfony\Component\HttpFoundation\Response + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ public function toResponse(): Response @@ -113,6 +123,8 @@ abstract class Handler /** * Return the notify message from request. * + * @return array + * * @throws \EasyWeChat\Kernel\Exceptions\Exception */ public function getMessage(): array @@ -141,6 +153,8 @@ abstract class Handler /** * Decrypt message. * + * @param string $key + * * @return string|null * * @throws \EasyWeChat\Kernel\Exceptions\Exception @@ -153,17 +167,15 @@ abstract class Handler } return Support\AES::decrypt( - base64_decode($message[$key], true), - md5($this->app['config']->key), - '', - OPENSSL_RAW_DATA, - 'AES-256-ECB' + base64_decode($message[$key], true), md5($this->app['config']->key), '', OPENSSL_RAW_DATA, 'AES-256-ECB' ); } /** * Validate the request params. * + * @param array $message + * * @throws \EasyWeChat\Payment\Kernel\Exceptions\InvalidSignException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ diff --git a/src/vendor/overtrue/wechat/src/Payment/Notify/Paid.php b/src/vendor/overtrue/wechat/src/Payment/Notify/Paid.php index 8e107bd76..c54b9cd34 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Notify/Paid.php +++ b/src/vendor/overtrue/wechat/src/Payment/Notify/Paid.php @@ -16,6 +16,8 @@ use Closure; class Paid extends Handler { /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @throws \EasyWeChat\Kernel\Exceptions\Exception diff --git a/src/vendor/overtrue/wechat/src/Payment/Notify/Refunded.php b/src/vendor/overtrue/wechat/src/Payment/Notify/Refunded.php index 2ff7eddac..824189225 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Notify/Refunded.php +++ b/src/vendor/overtrue/wechat/src/Payment/Notify/Refunded.php @@ -19,6 +19,8 @@ class Refunded extends Handler protected $check = false; /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @throws \EasyWeChat\Kernel\Exceptions\Exception diff --git a/src/vendor/overtrue/wechat/src/Payment/Notify/Scanned.php b/src/vendor/overtrue/wechat/src/Payment/Notify/Scanned.php index dfa9543c6..023a90541 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Notify/Scanned.php +++ b/src/vendor/overtrue/wechat/src/Payment/Notify/Scanned.php @@ -22,12 +22,17 @@ class Scanned extends Handler */ protected $alert; + /** + * @param string $message + */ public function alert(string $message) { $this->alert = $message; } /** + * @param \Closure $closure + * * @return \Symfony\Component\HttpFoundation\Response * * @throws \EasyWeChat\Kernel\Exceptions\Exception diff --git a/src/vendor/overtrue/wechat/src/Payment/Order/Client.php b/src/vendor/overtrue/wechat/src/Payment/Order/Client.php index 0be54ed18..ff2ca2b86 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Order/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Order/Client.php @@ -23,7 +23,8 @@ class Client extends BaseClient /** * Unify order. * - * @param bool $isContract + * @param array $params + * @param bool $isContract * * @return ResponseInterface|Collection|array|object|string * @@ -55,6 +56,8 @@ class Client extends BaseClient /** * Query order by out trade number. * + * @param string $number + * * @return ResponseInterface|Collection|array|object|string * * @throws InvalidArgumentException @@ -70,6 +73,8 @@ class Client extends BaseClient /** * Query order by transaction id. * + * @param string $transactionId + * * @return ResponseInterface|Collection|array|object|string * * @throws InvalidArgumentException @@ -83,6 +88,8 @@ class Client extends BaseClient } /** + * @param array $params + * * @return ResponseInterface|Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -99,6 +106,8 @@ class Client extends BaseClient /** * Close order by out_trade_no. * + * @param string $tradeNo + * * @return ResponseInterface|Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/ProfitSharing/Client.php b/src/vendor/overtrue/wechat/src/Payment/ProfitSharing/Client.php index 8b75b321b..d16ca2b1a 100644 --- a/src/vendor/overtrue/wechat/src/Payment/ProfitSharing/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/ProfitSharing/Client.php @@ -48,14 +48,12 @@ class Client extends BaseClient $params = [ 'appid' => $this->app['config']->app_id, 'receiver' => json_encode( - $receiver, - JSON_UNESCAPED_UNICODE + $receiver, JSON_UNESCAPED_UNICODE ), ]; return $this->request( - 'pay/profitsharingaddreceiver', - $params + 'pay/profitsharingaddreceiver', $params ); } @@ -77,14 +75,12 @@ class Client extends BaseClient $params = [ 'appid' => $this->app['config']->app_id, 'receiver' => json_encode( - $receiver, - JSON_UNESCAPED_UNICODE + $receiver, JSON_UNESCAPED_UNICODE ), ]; return $this->request( - 'pay/profitsharingremovereceiver', - $params + 'pay/profitsharingremovereceiver', $params ); } @@ -112,14 +108,12 @@ class Client extends BaseClient 'transaction_id' => $transactionId, 'out_order_no' => $outOrderNo, 'receivers' => json_encode( - $receivers, - JSON_UNESCAPED_UNICODE + $receivers, JSON_UNESCAPED_UNICODE ), ]; return $this->safeRequest( - 'secapi/pay/profitsharing', - $params + 'secapi/pay/profitsharing', $params ); } @@ -147,14 +141,12 @@ class Client extends BaseClient 'transaction_id' => $transactionId, 'out_order_no' => $outOrderNo, 'receivers' => json_encode( - $receivers, - JSON_UNESCAPED_UNICODE + $receivers, JSON_UNESCAPED_UNICODE ), ]; return $this->safeRequest( - 'secapi/pay/multiprofitsharing', - $params + 'secapi/pay/multiprofitsharing', $params ); } @@ -162,6 +154,8 @@ class Client extends BaseClient * Finish profit sharing. * 完结分账. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -174,8 +168,7 @@ class Client extends BaseClient $params['sub_appid'] = null; return $this->safeRequest( - 'secapi/pay/profitsharingfinish', - $params + 'secapi/pay/profitsharingfinish', $params ); } @@ -193,8 +186,7 @@ class Client extends BaseClient * @throws \GuzzleHttp\Exception\GuzzleException */ public function query( - string $transactionId, - string $outOrderNo + string $transactionId, string $outOrderNo ) { $params = [ 'sub_appid' => null, @@ -203,47 +195,7 @@ class Client extends BaseClient ]; return $this->request( - 'pay/profitsharingquery', - $params - ); - } - - /** - * Profit sharing return. - * 分账回退. - * - * @param string $outOrderNo 商户系统内部的分账单号 - * @param string $outReturnNo 商户系统内部分账回退单号 - * @param int $returnAmount 回退金额 - * @param string $returnAccount 回退方账号 - * @param string $description 回退描述 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function returnShare( - string $outOrderNo, - string $outReturnNo, - int $returnAmount, - string $returnAccount, - string $description - ) { - $params = [ - 'appid' => $this->app['config']->app_id, - 'out_order_no' => $outOrderNo, - 'out_return_no' => $outReturnNo, - 'return_account_type' => 'MERCHANT_ID', - 'return_account' => $returnAccount, - 'return_amount' => $returnAmount, - 'description' => $description, - ]; - - return $this->safeRequest( - 'secapi/pay/profitsharingreturn', - $params + 'pay/profitsharingquery', $params ); } } diff --git a/src/vendor/overtrue/wechat/src/Payment/Redpack/Client.php b/src/vendor/overtrue/wechat/src/Payment/Redpack/Client.php index 1f16fb029..63fe774a0 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Redpack/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Redpack/Client.php @@ -46,6 +46,8 @@ class Client extends BaseClient /** * Send miniprogram normal redpack. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -64,6 +66,8 @@ class Client extends BaseClient /** * Send normal redpack. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -84,6 +88,8 @@ class Client extends BaseClient /** * Send group redpack. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Refund/Client.php b/src/vendor/overtrue/wechat/src/Payment/Refund/Client.php index 0036bde29..128c6e701 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Refund/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Refund/Client.php @@ -18,6 +18,12 @@ class Client extends BaseClient /** * Refund by out trade number. * + * @param string $number + * @param string $refundNumber + * @param int $totalFee + * @param int $refundFee + * @param array $optional + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -30,6 +36,12 @@ class Client extends BaseClient /** * Refund by transaction id. * + * @param string $transactionId + * @param string $refundNumber + * @param int $totalFee + * @param int $refundFee + * @param array $optional + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +54,8 @@ class Client extends BaseClient /** * Query refund by transaction id. * + * @param string $transactionId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -54,6 +68,8 @@ class Client extends BaseClient /** * Query refund by out trade number. * + * @param string $outTradeNumber + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -66,6 +82,8 @@ class Client extends BaseClient /** * Query refund by out refund number. * + * @param string $outRefundNumber + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -78,6 +96,8 @@ class Client extends BaseClient /** * Query refund by refund id. * + * @param string $refundId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -90,7 +110,10 @@ class Client extends BaseClient /** * Refund. * - * @param array $optional + * @param string $refundNumber + * @param int $totalFee + * @param int $refundFee + * @param array $optional * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * @@ -115,6 +138,9 @@ class Client extends BaseClient /** * Query refund. * + * @param string $number + * @param string $type + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Reverse/Client.php b/src/vendor/overtrue/wechat/src/Payment/Reverse/Client.php index ee0b2459b..990e6e6d5 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Reverse/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Reverse/Client.php @@ -18,6 +18,8 @@ class Client extends BaseClient /** * Reverse order by out trade number. * + * @param string $outTradeNumber + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -30,6 +32,8 @@ class Client extends BaseClient /** * Reverse order by transaction_id. * + * @param string $transactionId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -42,6 +46,9 @@ class Client extends BaseClient /** * Reverse order. * + * @param string $number + * @param string $type + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Payment/Sandbox/Client.php b/src/vendor/overtrue/wechat/src/Payment/Sandbox/Client.php index e5a6b44d2..9f1ec7ce2 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Sandbox/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Sandbox/Client.php @@ -25,6 +25,8 @@ class Client extends BaseClient use InteractsWithCache; /** + * @return string + * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Payment\Kernel\Exceptions\SandboxException * @throws \Psr\SimpleCache\InvalidArgumentException @@ -48,6 +50,9 @@ class Client extends BaseClient throw new SandboxException($response['retmsg'] ?? $response['return_msg']); } + /** + * @return string + */ protected function getCacheKey(): string { return 'easywechat.payment.sandbox.'.md5($this->app['config']->app_id.$this->app['config']['mch_id']); diff --git a/src/vendor/overtrue/wechat/src/Payment/Sandbox/ServiceProvider.php b/src/vendor/overtrue/wechat/src/Payment/Sandbox/ServiceProvider.php index 05fb7dd7c..d0b5d6e86 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Sandbox/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Payment/Sandbox/ServiceProvider.php @@ -21,6 +21,9 @@ use Pimple\ServiceProviderInterface; */ class ServiceProvider implements ServiceProviderInterface { + /** + * @param \Pimple\Container $app + */ public function register(Container $app) { $app['sandbox'] = function ($app) { diff --git a/src/vendor/overtrue/wechat/src/Payment/Transfer/Client.php b/src/vendor/overtrue/wechat/src/Payment/Transfer/Client.php index 1e80c68d6..b8a7c443a 100644 --- a/src/vendor/overtrue/wechat/src/Payment/Transfer/Client.php +++ b/src/vendor/overtrue/wechat/src/Payment/Transfer/Client.php @@ -12,9 +12,9 @@ namespace EasyWeChat\Payment\Transfer; use EasyWeChat\Kernel\Exceptions\RuntimeException; -use EasyWeChat\Payment\Kernel\BaseClient; use function EasyWeChat\Kernel\Support\get_server_ip; use function EasyWeChat\Kernel\Support\rsa_public_encrypt; +use EasyWeChat\Payment\Kernel\BaseClient; /** * Class Client. @@ -26,6 +26,8 @@ class Client extends BaseClient /** * Query MerchantPay to balance. * + * @param string $partnerTradeNo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -46,6 +48,8 @@ class Client extends BaseClient /** * Send MerchantPay to balance. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -70,6 +74,8 @@ class Client extends BaseClient /** * Query MerchantPay order to BankCard. * + * @param string $partnerTradeNo + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -89,6 +95,8 @@ class Client extends BaseClient /** * Send MerchantPay to BankCard. * + * @param array $params + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Work/Agent/Client.php b/src/vendor/overtrue/wechat/src/Work/Agent/Client.php index f049883db..9e11aac5f 100644 --- a/src/vendor/overtrue/wechat/src/Work/Agent/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Agent/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Get agent. * + * @param int $agentId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -39,6 +41,9 @@ class Client extends BaseClient /** * Set agent. * + * @param int $agentId + * @param array $attributes + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Application.php b/src/vendor/overtrue/wechat/src/Work/Application.php index 30d424115..1aac05850 100644 --- a/src/vendor/overtrue/wechat/src/Work/Application.php +++ b/src/vendor/overtrue/wechat/src/Work/Application.php @@ -29,7 +29,7 @@ use EasyWeChat\Work\MiniProgram\Application as MiniProgram; * @property \EasyWeChat\Work\Message\Messenger $messenger * @property \EasyWeChat\Work\User\Client $user * @property \EasyWeChat\Work\User\TagClient $tag - * @property \EasyWeChat\Work\Server\Guard $server + * @property \EasyWeChat\Work\Server\ServiceProvider $server * @property \EasyWeChat\Work\Jssdk\Client $jssdk * @property \Overtrue\Socialite\Providers\WeWorkProvider $oauth * @property \EasyWeChat\Work\Invoice\Client $invoice @@ -42,8 +42,6 @@ use EasyWeChat\Work\MiniProgram\Application as MiniProgram; * @property \EasyWeChat\Work\GroupRobot\Messenger $group_robot_messenger * @property \EasyWeChat\Work\Calendar\Client $calendar * @property \EasyWeChat\Work\Schedule\Client $schedule - * @property \EasyWeChat\Work\MsgAudit\Client $msg_audit - * @property \EasyWeChat\Work\ExternalContact\SchoolClient $school * * @method mixed getCallbackIp() */ @@ -71,7 +69,6 @@ class Application extends ServiceContainer GroupRobot\ServiceProvider::class, Calendar\ServiceProvider::class, Schedule\ServiceProvider::class, - MsgAudit\ServiceProvider::class, ]; /** @@ -86,6 +83,8 @@ class Application extends ServiceContainer /** * Creates the miniProgram application. + * + * @return \EasyWeChat\Work\MiniProgram\Application */ public function miniProgram(): MiniProgram { diff --git a/src/vendor/overtrue/wechat/src/Work/Auth/AccessToken.php b/src/vendor/overtrue/wechat/src/Work/Auth/AccessToken.php index 2ad59d417..56d521855 100644 --- a/src/vendor/overtrue/wechat/src/Work/Auth/AccessToken.php +++ b/src/vendor/overtrue/wechat/src/Work/Auth/AccessToken.php @@ -32,6 +32,8 @@ class AccessToken extends BaseAccessToken /** * Credential for get token. + * + * @return array */ protected function getCredentials(): array { diff --git a/src/vendor/overtrue/wechat/src/Work/Base/ServiceProvider.php b/src/vendor/overtrue/wechat/src/Work/Base/ServiceProvider.php index 375eb76a4..5e28fd19f 100644 --- a/src/vendor/overtrue/wechat/src/Work/Base/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Work/Base/ServiceProvider.php @@ -21,6 +21,9 @@ use Pimple\ServiceProviderInterface; */ class ServiceProvider implements ServiceProviderInterface { + /** + * @param Container $app + */ public function register(Container $app) { $app['base'] = function ($app) { diff --git a/src/vendor/overtrue/wechat/src/Work/Calendar/Client.php b/src/vendor/overtrue/wechat/src/Work/Calendar/Client.php index ed6e99de8..90a684931 100644 --- a/src/vendor/overtrue/wechat/src/Work/Calendar/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Calendar/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Add a calendar. * + * @param array $calendar + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,9 @@ class Client extends BaseClient /** * Update the calendar. * + * @param string $id + * @param array $calendar + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -66,6 +71,8 @@ class Client extends BaseClient /** * Delete a calendar. * + * @param string $id + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Chat/Client.php b/src/vendor/overtrue/wechat/src/Work/Chat/Client.php index 888198978..0d4fdecc5 100644 --- a/src/vendor/overtrue/wechat/src/Work/Chat/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Chat/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Get chat. * + * @param string $chatId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -35,6 +37,8 @@ class Client extends BaseClient /** * Create chat. * + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -48,6 +52,9 @@ class Client extends BaseClient /** * Update chat. * + * @param string $chatId + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -61,6 +68,8 @@ class Client extends BaseClient /** * Send a message. * + * @param array $message + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Department/Client.php b/src/vendor/overtrue/wechat/src/Work/Department/Client.php index 3b2304290..c34cc8694 100644 --- a/src/vendor/overtrue/wechat/src/Work/Department/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Department/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Create a department. * + * @param array $data + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,9 @@ class Client extends BaseClient /** * Update a department. * + * @param int $id + * @param array $data + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/ExternalContact/Client.php b/src/vendor/overtrue/wechat/src/Work/ExternalContact/Client.php index 327f25dcd..477686fd8 100644 --- a/src/vendor/overtrue/wechat/src/Work/ExternalContact/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/ExternalContact/Client.php @@ -39,6 +39,8 @@ class Client extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91555 * + * @param string $userId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -55,6 +57,8 @@ class Client extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91556 * + * @param string $externalUserId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -66,45 +70,14 @@ class Client extends BaseClient ]); } - /** - * 批量获取外部联系人详情. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92994 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - */ - public function batchGetUsers(array $data) - { - return $this->httpPostJson( - 'cgi-bin/externalcontact/batch/get_by_user', - $data - ); - } - - /** - * 修改客户备注信息. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92115 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - */ - public function remark(array $data) - { - return $this->httpPostJson( - 'cgi-bin/externalcontact/remark', - $data - ); - } - /** * 获取离职成员的客户列表. * * @see https://work.weixin.qq.com/api/doc#90000/90135/91563 * + * @param int $pageId + * @param int $pageSize + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -123,6 +96,10 @@ class Client extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91564 * + * @param string $externalUserId + * @param string $handoverUserId + * @param string $takeoverUserId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -138,128 +115,4 @@ class Client extends BaseClient return $this->httpPostJson('cgi-bin/externalcontact/transfer', $params); } - - /** - * 获取客户群列表. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92120 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function getGroupChats(array $params) - { - return $this->httpPostJson('cgi-bin/externalcontact/groupchat/list', $params); - } - - /** - * 获取客户群详情. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92122 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function getGroupChat(string $chatId) - { - $params = [ - 'chat_id' => $chatId, - ]; - - return $this->httpPostJson('cgi-bin/externalcontact/groupchat/get', $params); - } - - /** - * 获取企业标签库. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92117#获取企业标签库 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function getCorpTags(array $tagIds = []) - { - $params = [ - 'tag_id' => $tagIds, - ]; - - return $this->httpPostJson('cgi-bin/externalcontact/get_corp_tag_list', $params); - } - - /** - * 添加企业客户标签. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92117#添加企业客户标签 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function addCorpTag(array $params) - { - return $this->httpPostJson('cgi-bin/externalcontact/add_corp_tag', $params); - } - - /** - * 编辑企业客户标签. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92117#编辑企业客户标签 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function updateCorpTag(string $id, string $name, int $order = 1) - { - $params = [ - 'id' => $id, - 'name' => $name, - 'order' => $order, - ]; - - return $this->httpPostJson('cgi-bin/externalcontact/edit_corp_tag', $params); - } - - /** - * 删除企业客户标签. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92117#删除企业客户标签 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function deleteCorpTag(array $tagId, array $groupId) - { - $params = [ - 'tag_id' => $tagId, - 'group_id' => $groupId, - ]; - - return $this->httpPostJson('cgi-bin/externalcontact/del_corp_tag', $params); - } - - /** - * 编辑客户企业标签. - * - * @see https://work.weixin.qq.com/api/doc/90000/90135/92118 - * - * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function markTags(array $params) - { - return $this->httpPostJson('cgi-bin/externalcontact/mark_tag', $params); - } } diff --git a/src/vendor/overtrue/wechat/src/Work/ExternalContact/ContactWayClient.php b/src/vendor/overtrue/wechat/src/Work/ExternalContact/ContactWayClient.php index e373f947f..7cfc2bbad 100644 --- a/src/vendor/overtrue/wechat/src/Work/ExternalContact/ContactWayClient.php +++ b/src/vendor/overtrue/wechat/src/Work/ExternalContact/ContactWayClient.php @@ -23,6 +23,10 @@ class ContactWayClient extends BaseClient /** * 配置客户联系「联系我」方式. * + * @param int $type + * @param int $scene + * @param array $config + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +45,8 @@ class ContactWayClient extends BaseClient /** * 获取企业已配置的「联系我」方式. * + * @param string $configId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -56,6 +62,9 @@ class ContactWayClient extends BaseClient /** * 更新企业已配置的「联系我」方式. * + * @param string $configId + * @param array $config + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -73,6 +82,8 @@ class ContactWayClient extends BaseClient /** * 删除企业已配置的「联系我」方式. * + * @param string $configId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/ExternalContact/MessageClient.php b/src/vendor/overtrue/wechat/src/Work/ExternalContact/MessageClient.php index db21997c3..ce00f809b 100644 --- a/src/vendor/overtrue/wechat/src/Work/ExternalContact/MessageClient.php +++ b/src/vendor/overtrue/wechat/src/Work/ExternalContact/MessageClient.php @@ -55,6 +55,8 @@ class MessageClient extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91560 * + * @param array $msg + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -73,6 +75,8 @@ class MessageClient extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91561 * + * @param string $msgId + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -90,6 +94,9 @@ class MessageClient extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91688 * + * @param string $welcomeCode + * @param array $msg + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException @@ -108,6 +115,8 @@ class MessageClient extends BaseClient } /** + * @param array $data + * * @return array * * @throws InvalidArgumentException @@ -136,6 +145,9 @@ class MessageClient extends BaseClient } /** + * @param array $data + * @param array $default + * * @return array * * @throws InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Work/ExternalContact/ServiceProvider.php b/src/vendor/overtrue/wechat/src/Work/ExternalContact/ServiceProvider.php index 2d4af0569..b76630a02 100644 --- a/src/vendor/overtrue/wechat/src/Work/ExternalContact/ServiceProvider.php +++ b/src/vendor/overtrue/wechat/src/Work/ExternalContact/ServiceProvider.php @@ -41,9 +41,5 @@ class ServiceProvider implements ServiceProviderInterface $app['external_contact_message'] = function ($app) { return new MessageClient($app); }; - - $app['school'] = function ($app){ - return new SchoolClient($app); - }; } } diff --git a/src/vendor/overtrue/wechat/src/Work/ExternalContact/StatisticsClient.php b/src/vendor/overtrue/wechat/src/Work/ExternalContact/StatisticsClient.php index cb19da782..c6922df08 100644 --- a/src/vendor/overtrue/wechat/src/Work/ExternalContact/StatisticsClient.php +++ b/src/vendor/overtrue/wechat/src/Work/ExternalContact/StatisticsClient.php @@ -25,6 +25,10 @@ class StatisticsClient extends BaseClient * * @see https://work.weixin.qq.com/api/doc#90000/90135/91580 * + * @param array $userIds + * @param string $from + * @param string $to + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Client.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Client.php index 3b3df8aa8..c2e0aa0bc 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Client.php @@ -34,6 +34,9 @@ class Client extends BaseClient } /** + * @param string $key + * @param array $message + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Image.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Image.php index 8ba69b087..14beb81c3 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Image.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Image.php @@ -30,6 +30,9 @@ class Image extends Message /** * Image constructor. + * + * @param string $base64 + * @param string $md5 */ public function __construct(string $base64, string $md5) { diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Markdown.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Markdown.php index f26ac6fd0..dfe6980c5 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Markdown.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Markdown.php @@ -30,6 +30,8 @@ class Markdown extends Message /** * Markdown constructor. + * + * @param string $content */ public function __construct(string $content) { diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/News.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/News.php index eeb37f0a8..835023e78 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/News.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/News.php @@ -30,12 +30,20 @@ class News extends Message /** * News constructor. + * + * @param array $items */ public function __construct(array $items = []) { parent::__construct(compact('items')); } + /** + * @param array $data + * @param array $aliases + * + * @return array + */ public function propertiesToArray(array $data, array $aliases = []): array { return ['articles' => array_map(function ($item) { diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Text.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Text.php index db7c2f845..a1e6dda04 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Text.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messages/Text.php @@ -31,6 +31,7 @@ class Text extends Message /** * Text constructor. * + * @param string $content * @param string|array $userIds * @param string|array $mobiles */ diff --git a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messenger.php b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messenger.php index 5a4e9c562..573296a95 100644 --- a/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messenger.php +++ b/src/vendor/overtrue/wechat/src/Work/GroupRobot/Messenger.php @@ -41,6 +41,8 @@ class Messenger /** * Messenger constructor. + * + * @param Client $client */ public function __construct(Client $client) { @@ -70,6 +72,8 @@ class Messenger } /** + * @param string $groupKey + * * @return Messenger */ public function toGroup(string $groupKey) diff --git a/src/vendor/overtrue/wechat/src/Work/Invoice/Client.php b/src/vendor/overtrue/wechat/src/Work/Invoice/Client.php index 8dbc8b954..edbd34ba5 100644 --- a/src/vendor/overtrue/wechat/src/Work/Invoice/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Invoice/Client.php @@ -21,6 +21,9 @@ use EasyWeChat\Kernel\BaseClient; class Client extends BaseClient { /** + * @param string $cardId + * @param string $encryptCode + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -37,6 +40,8 @@ class Client extends BaseClient } /** + * @param array $invoices + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -52,6 +57,10 @@ class Client extends BaseClient } /** + * @param string $cardId + * @param string $encryptCode + * @param string $status + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -69,6 +78,10 @@ class Client extends BaseClient } /** + * @param array $invoices + * @param string $openid + * @param string $status + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Jssdk/Client.php b/src/vendor/overtrue/wechat/src/Work/Jssdk/Client.php index 752c26fcc..40fc368fc 100644 --- a/src/vendor/overtrue/wechat/src/Work/Jssdk/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Jssdk/Client.php @@ -13,7 +13,6 @@ namespace EasyWeChat\Work\Jssdk; use EasyWeChat\BasicService\Jssdk\Client as BaseClient; use EasyWeChat\Kernel\Exceptions\RuntimeException; -use EasyWeChat\Kernel\Support; /** * Class Client. @@ -33,126 +32,9 @@ class Client extends BaseClient } /** - * @return string - */ - protected function getAgentId() - { - return $this->app['config']->get('agent_id'); - } - - /** - * @param array $apis - * @param $agentId - * @param bool $debug - * @param bool $beta - * @param array $openTagList - * @param string|null $url - * - * @return array|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Psr\SimpleCache\InvalidArgumentException - */ - public function getAgentConfigArray(array $apis, $agentId, bool $debug = false, bool $beta = false, array $openTagList = [], string $url = null) - { - return $this->buildAgentConfig($apis, $agentId, $debug, $beta, false, $openTagList, $url); - } - - /** - * @param array $jsApiList - * @param $agentId - * @param bool $debug - * @param bool $beta - * @param bool $json - * @param array $openTagList - * @param string|null $url - * - * @return array|string - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Psr\SimpleCache\InvalidArgumentException - */ - public function buildAgentConfig(array $jsApiList, $agentId, bool $debug = false, bool $beta = false, bool $json = true, array $openTagList = [], string $url = null) - { - $config = array_merge(compact('debug', 'beta', 'jsApiList', 'openTagList'), $this->agentConfigSignature($agentId, $url)); - - return $json ? json_encode($config) : $config; - } - - /** - * @param $agentId - * @param string|null $url - * @param string|null $nonce - * @param null $timestamp - * - * @return array - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Psr\SimpleCache\InvalidArgumentException - */ - protected function agentConfigSignature($agentId, string $url = null, string $nonce = null, $timestamp = null): array - { - $url = $url ?: $this->getUrl(); - $nonce = $nonce ?: Support\Str::quickRandom(10); - $timestamp = $timestamp ?: time(); - - return [ - 'corpid' => $this->getAppId(), - 'agentid' => $agentId, - 'nonceStr' => $nonce, - 'timestamp' => $timestamp, - 'url' => $url, - 'signature' => $this->getTicketSignature($this->getAgentTicket()['ticket'], $nonce, $timestamp, $url), - ]; - } - - /** - * Get js ticket. - * * @param bool $refresh * @param string $type * - * @return array - * - * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException - * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException - * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \Psr\SimpleCache\InvalidArgumentException - */ - public function getTicket(bool $refresh = false, string $type = 'config'): array - { - $cacheKey = sprintf('easywechat.work.jssdk.ticket.%s.%s', $type, $this->getAppId()); - - if (!$refresh && $this->getCache()->has($cacheKey)) { - return $this->getCache()->get($cacheKey); - } - - /** @var array $result */ - $result = $this->castResponseToType( - $this->requestRaw($this->ticketEndpoint, 'GET'), - 'array' - ); - - $this->getCache()->set($cacheKey, $result, $result['expires_in'] - 500); - - if (!$this->getCache()->has($cacheKey)) { - throw new RuntimeException('Failed to cache jssdk ticket.'); - } - - return $result; - } - - /** * @return array|\EasyWeChat\Kernel\Support\Collection|mixed|object|\Psr\Http\Message\ResponseInterface|string * * @throws RuntimeException @@ -163,7 +45,7 @@ class Client extends BaseClient */ public function getAgentTicket(bool $refresh = false, string $type = 'agent_config') { - $cacheKey = sprintf('easywechat.work.jssdk.ticket.%s.%s.%s', $type, $this->getAppId(), $this->getAgentId()); + $cacheKey = sprintf('easywechat.work.jssdk.ticket.%s.%s', $type, $this->getAppId()); if (!$refresh && $this->getCache()->has($cacheKey)) { return $this->getCache()->get($cacheKey); diff --git a/src/vendor/overtrue/wechat/src/Work/Media/Client.php b/src/vendor/overtrue/wechat/src/Work/Media/Client.php index 285a11a83..16e8a9462 100644 --- a/src/vendor/overtrue/wechat/src/Work/Media/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Media/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * Get media. * + * @param string $mediaId + * * @return array|\EasyWeChat\Kernel\Http\Response|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -47,6 +49,8 @@ class Client extends BaseClient /** * Upload Image. * + * @param string $path + * * @return mixed */ public function uploadImage(string $path) @@ -57,6 +61,8 @@ class Client extends BaseClient /** * Upload Voice. * + * @param string $path + * * @return mixed */ public function uploadVoice(string $path) @@ -67,6 +73,8 @@ class Client extends BaseClient /** * Upload Video. * + * @param string $path + * * @return mixed */ public function uploadVideo(string $path) @@ -77,6 +85,8 @@ class Client extends BaseClient /** * Upload File. * + * @param string $path + * * @return mixed */ public function uploadFile(string $path) @@ -87,6 +97,9 @@ class Client extends BaseClient /** * Upload media. * + * @param string $type + * @param string $path + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Menu/Client.php b/src/vendor/overtrue/wechat/src/Work/Menu/Client.php index bdb8850d1..e57a3a168 100644 --- a/src/vendor/overtrue/wechat/src/Work/Menu/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Menu/Client.php @@ -35,6 +35,8 @@ class Client extends BaseClient /** * Create menu for the given agent. * + * @param array $data + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Message/Client.php b/src/vendor/overtrue/wechat/src/Work/Message/Client.php index 9690f1ebf..149758692 100644 --- a/src/vendor/overtrue/wechat/src/Work/Message/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Message/Client.php @@ -34,6 +34,8 @@ class Client extends BaseClient } /** + * @param array $message + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Message/Messenger.php b/src/vendor/overtrue/wechat/src/Work/Message/Messenger.php index a9796f504..62bc62d0f 100644 --- a/src/vendor/overtrue/wechat/src/Work/Message/Messenger.php +++ b/src/vendor/overtrue/wechat/src/Work/Message/Messenger.php @@ -83,6 +83,8 @@ class Messenger } /** + * @param int $agentId + * * @return \EasyWeChat\Work\Message\Messenger */ public function ofAgent(int $agentId) @@ -136,6 +138,7 @@ class Messenger /** * @param array|string $ids + * @param string $key * * @return \EasyWeChat\Work\Message\Messenger */ diff --git a/src/vendor/overtrue/wechat/src/Work/MiniProgram/Application.php b/src/vendor/overtrue/wechat/src/Work/MiniProgram/Application.php index abc425f76..aa290cd07 100644 --- a/src/vendor/overtrue/wechat/src/Work/MiniProgram/Application.php +++ b/src/vendor/overtrue/wechat/src/Work/MiniProgram/Application.php @@ -26,6 +26,9 @@ class Application extends MiniProgram { /** * Application constructor. + * + * @param array $config + * @param array $prepends */ public function __construct(array $config = [], array $prepends = []) { diff --git a/src/vendor/overtrue/wechat/src/Work/MiniProgram/Auth/Client.php b/src/vendor/overtrue/wechat/src/Work/MiniProgram/Auth/Client.php index 71f79c4df..ac9baffc5 100644 --- a/src/vendor/overtrue/wechat/src/Work/MiniProgram/Auth/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/MiniProgram/Auth/Client.php @@ -21,6 +21,8 @@ class Client extends BaseClient /** * Get session info by code. * + * @param string $code + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/OA/Client.php b/src/vendor/overtrue/wechat/src/Work/OA/Client.php index c89f4636e..483d8924d 100644 --- a/src/vendor/overtrue/wechat/src/Work/OA/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/OA/Client.php @@ -23,6 +23,11 @@ class Client extends BaseClient /** * Get the checkin data. * + * @param int $startTime + * @param int $endTime + * @param array $userList + * @param int $type + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -43,6 +48,9 @@ class Client extends BaseClient /** * Get the checkin rules. * + * @param int $datetime + * @param array $userList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -61,6 +69,8 @@ class Client extends BaseClient /** * Get approval template details. * + * @param string $templateId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -78,6 +88,8 @@ class Client extends BaseClient /** * Submit an application for approval. * + * @param array $data + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -91,6 +103,12 @@ class Client extends BaseClient /** * Get Approval number. * + * @param int $startTime + * @param int $endTime + * @param int $nextCursor + * @param int $size + * @param array $filters + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -112,6 +130,8 @@ class Client extends BaseClient /** * Get approval detail. * + * @param int $number + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -129,6 +149,8 @@ class Client extends BaseClient /** * Get Approval Data. * + * @param int $startTime + * @param int $endTime * @param int $nextNumber * * @return mixed diff --git a/src/vendor/overtrue/wechat/src/Work/OAuth/AccessTokenDelegate.php b/src/vendor/overtrue/wechat/src/Work/OAuth/AccessTokenDelegate.php index dc41b3228..9acfbbb48 100644 --- a/src/vendor/overtrue/wechat/src/Work/OAuth/AccessTokenDelegate.php +++ b/src/vendor/overtrue/wechat/src/Work/OAuth/AccessTokenDelegate.php @@ -26,6 +26,9 @@ class AccessTokenDelegate implements AccessTokenInterface */ protected $app; + /** + * @param \EasyWeChat\Work\Application $app + */ public function __construct(Application $app) { $this->app = $app; diff --git a/src/vendor/overtrue/wechat/src/Work/Schedule/Client.php b/src/vendor/overtrue/wechat/src/Work/Schedule/Client.php index b873a0194..ba41ddbeb 100644 --- a/src/vendor/overtrue/wechat/src/Work/Schedule/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/Schedule/Client.php @@ -23,6 +23,8 @@ class Client extends BaseClient /** * Add a schedule. * + * @param array $schedule + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -36,6 +38,9 @@ class Client extends BaseClient /** * Update the schedule. * + * @param string $id + * @param array $schedule + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -66,6 +71,10 @@ class Client extends BaseClient /** * Get the list of schedules under a calendar. * + * @param string $calendarId + * @param int $offset + * @param int $limit + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -81,6 +90,8 @@ class Client extends BaseClient /** * Delete a schedule. * + * @param string $id + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/overtrue/wechat/src/Work/Server/Guard.php b/src/vendor/overtrue/wechat/src/Work/Server/Guard.php index aac3d8f65..b77c6c1c2 100644 --- a/src/vendor/overtrue/wechat/src/Work/Server/Guard.php +++ b/src/vendor/overtrue/wechat/src/Work/Server/Guard.php @@ -30,12 +30,17 @@ class Guard extends ServerGuard /** * Check the request message safe mode. + * + * @return bool */ protected function isSafeMode(): bool { return true; } + /** + * @return bool + */ protected function shouldReturnRawResponse(): bool { return !is_null($this->app['request']->get('echostr')); diff --git a/src/vendor/overtrue/wechat/src/Work/Server/Handlers/EchoStrHandler.php b/src/vendor/overtrue/wechat/src/Work/Server/Handlers/EchoStrHandler.php index 6427ba5e8..64555ef02 100644 --- a/src/vendor/overtrue/wechat/src/Work/Server/Handlers/EchoStrHandler.php +++ b/src/vendor/overtrue/wechat/src/Work/Server/Handlers/EchoStrHandler.php @@ -29,6 +29,8 @@ class EchoStrHandler implements EventHandlerInterface /** * EchoStrHandler constructor. + * + * @param ServiceContainer $app */ public function __construct(ServiceContainer $app) { diff --git a/src/vendor/overtrue/wechat/src/Work/User/Client.php b/src/vendor/overtrue/wechat/src/Work/User/Client.php index 9141fc7f6..8c07ec67a 100644 --- a/src/vendor/overtrue/wechat/src/Work/User/Client.php +++ b/src/vendor/overtrue/wechat/src/Work/User/Client.php @@ -24,6 +24,8 @@ class Client extends BaseClient /** * Create a user. * + * @param array $data + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -37,6 +39,9 @@ class Client extends BaseClient /** * Update an exist user. * + * @param string $id + * @param array $data + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -69,6 +74,8 @@ class Client extends BaseClient /** * Batch delete users. * + * @param array $userIds + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -82,6 +89,8 @@ class Client extends BaseClient /** * Get user. * + * @param string $userId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -94,6 +103,9 @@ class Client extends BaseClient /** * Get simple user list. * + * @param int $departmentId + * @param bool $fetchChild + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -111,6 +123,9 @@ class Client extends BaseClient /** * Get user list. * + * @param int $departmentId + * @param bool $fetchChild + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -128,6 +143,9 @@ class Client extends BaseClient /** * Convert userId to openid. * + * @param string $userId + * @param int|null $agentId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -146,6 +164,8 @@ class Client extends BaseClient /** * Convert openid to userId. * + * @param string $openid + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -163,6 +183,8 @@ class Client extends BaseClient /** * Convert mobile to userId. * + * @param string $mobile + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -178,6 +200,8 @@ class Client extends BaseClient } /** + * @param string $userId + * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -194,6 +218,8 @@ class Client extends BaseClient /** * Batch invite users. * + * @param array $params + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -207,6 +233,8 @@ class Client extends BaseClient /** * Get invitation QR code. * + * @param int $sizeType + * * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * * @throws InvalidArgumentException diff --git a/src/vendor/overtrue/wechat/src/Work/User/TagClient.php b/src/vendor/overtrue/wechat/src/Work/User/TagClient.php index c8d31f91b..aae7cf1ca 100644 --- a/src/vendor/overtrue/wechat/src/Work/User/TagClient.php +++ b/src/vendor/overtrue/wechat/src/Work/User/TagClient.php @@ -23,6 +23,9 @@ class TagClient extends BaseClient /** * Create tag. * + * @param string $tagName + * @param int|null $tagId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -41,6 +44,9 @@ class TagClient extends BaseClient /** * Update tag. * + * @param int $tagId + * @param string $tagName + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -59,6 +65,8 @@ class TagClient extends BaseClient /** * Delete tag. * + * @param int $tagId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -69,6 +77,8 @@ class TagClient extends BaseClient } /** + * @param int $tagId + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -79,6 +89,9 @@ class TagClient extends BaseClient } /** + * @param int $tagId + * @param array $userList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -90,6 +103,9 @@ class TagClient extends BaseClient } /** + * @param int $tagId + * @param array $partyList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -101,6 +117,9 @@ class TagClient extends BaseClient } /** + * @param int $tagId + * @param array $userList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -112,6 +131,9 @@ class TagClient extends BaseClient } /** + * @param int $tagId + * @param array $partyList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException @@ -123,6 +145,11 @@ class TagClient extends BaseClient } /** + * @param string $endpoint + * @param int $tagId + * @param array $userList + * @param array $partyList + * * @return mixed * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php index 20b1ec3f5..0c754daf7 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation.php @@ -2548,7 +2548,7 @@ class PHPExcel_Calculation public static function unwrapResult($value) { if (is_string($value)) { - if ((isset($value{0})) && ($value{0} == '"') && (substr($value, -1) == '"')) { + if ((isset($value[0])) && ($value[0] == '"') && (substr($value, -1) == '"')) { return substr($value, 1, -1); } // Convert numeric errors to NaN error @@ -2669,11 +2669,11 @@ class PHPExcel_Calculation // Basic validation that this is indeed a formula // We return an empty array if not $formula = trim($formula); - if ((!isset($formula{0})) || ($formula{0} != '=')) { + if ((!isset($formula[0])) || ($formula[0] != '=')) { return array(); } $formula = ltrim(substr($formula, 1)); - if (!isset($formula{0})) { + if (!isset($formula[0])) { return array(); } @@ -2761,11 +2761,11 @@ class PHPExcel_Calculation // Basic validation that this is indeed a formula // We simply return the cell value if not $formula = trim($formula); - if ($formula{0} != '=') { + if ($formula[0] != '=') { return self::wrapResult($formula); } $formula = ltrim(substr($formula, 1)); - if (!isset($formula{0})) { + if (!isset($formula[0])) { return self::wrapResult($formula); } @@ -2777,7 +2777,7 @@ class PHPExcel_Calculation return $cellValue; } - if (($wsTitle{0} !== "\x00") && ($this->cyclicReferenceStack->onStack($wsCellReference))) { + if (($wsTitle[0] !== "\x00") && ($this->cyclicReferenceStack->onStack($wsCellReference))) { if ($this->cyclicFormulaCount <= 0) { $this->cyclicFormulaCell = ''; return $this->raiseFormulaError('Cyclic Reference in Formula'); @@ -3031,7 +3031,7 @@ class PHPExcel_Calculation } else { if ($value == '') { return 'an empty string'; - } elseif ($value{0} == '#') { + } elseif ($value[0] == '#') { return 'a '.$value.' error'; } else { $typeString = 'a string'; @@ -3163,10 +3163,10 @@ class PHPExcel_Calculation // Loop through the formula extracting each operator and operand in turn while (true) { //echo 'Assessing Expression '.substr($formula, $index), PHP_EOL; - $opCharacter = $formula{$index}; // Get the first character of the value at the current index position + $opCharacter = $formula[$index]; // Get the first character of the value at the current index position //echo 'Initial character of expression block is '.$opCharacter, PHP_EOL; - if ((isset(self::$comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$comparisonOperators[$formula{$index+1}]))) { - $opCharacter .= $formula{++$index}; + if ((isset(self::$comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$comparisonOperators[$formula[$index+1]]))) { + $opCharacter .= $formula[++$index]; //echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL; } @@ -3454,11 +3454,11 @@ class PHPExcel_Calculation } } // Ignore white space - while (($formula{$index} == "\n") || ($formula{$index} == "\r")) { + while (($formula[$index] == "\n") || ($formula[$index] == "\r")) { ++$index; } - if ($formula{$index} == ' ') { - while ($formula{$index} == ' ') { + if ($formula[$index] == ' ') { + while ($formula[$index] == ' ') { ++$index; } // If we're expecting an operator, but only have a space between the previous and next operands (and both are @@ -3888,7 +3888,7 @@ class PHPExcel_Calculation // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; $stack->push('Constant Value', self::$excelConstants[$excelConstant]); $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->showTypeDetails(self::$excelConstants[$excelConstant])); - } elseif ((is_numeric($token)) || ($token === null) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { + } elseif ((is_numeric($token)) || ($token === null) || (is_bool($token)) || ($token == '') || ($token[0] == '"') || ($token[0] == '#')) { // echo 'Token is a number, boolean, string, null or an Excel error
'; $stack->push('Value', $token); // if the token is a named range, push the named range name onto the stack @@ -3933,13 +3933,13 @@ class PHPExcel_Calculation if (is_string($operand)) { // We only need special validations for the operand if it is a string // Start by stripping off the quotation marks we use to identify true excel string values internally - if ($operand > '' && $operand{0} == '"') { + if ($operand > '' && $operand[0] == '"') { $operand = self::unwrapResult($operand); } // If the string is a numeric value, we treat it as a numeric, so no further testing if (!is_numeric($operand)) { // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations - if ($operand > '' && $operand{0} == '#') { + if ($operand > '' && $operand[0] == '#') { $stack->push('Value', $operand); $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($operand)); return false; @@ -3995,10 +3995,10 @@ class PHPExcel_Calculation } // Simple validate the two operands if they are string values - if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { + if (is_string($operand1) && $operand1 > '' && $operand1[0] == '"') { $operand1 = self::unwrapResult($operand1); } - if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { + if (is_string($operand2) && $operand2 > '' && $operand2[0] == '"') { $operand2 = self::unwrapResult($operand2); } diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation/Functions.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation/Functions.php index b8b784fe5..5a5f60bbe 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation/Functions.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation/Functions.php @@ -318,10 +318,10 @@ class PHPExcel_Calculation_Functions public static function ifCondition($condition) { $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); - if (!isset($condition{0})) { + if (!isset($condition[0])) { $condition = '=""'; } - if (!in_array($condition{0}, array('>', '<', '='))) { + if (!in_array($condition[0], array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::wrapResult(strtoupper($condition)); } @@ -558,7 +558,7 @@ class PHPExcel_Calculation_Functions return (integer) $value; case 'string': // Errors - if ((strlen($value) > 0) && ($value{0} == '#')) { + if ((strlen($value) > 0) && ($value[0] == '#')) { return $value; } break; @@ -608,7 +608,7 @@ class PHPExcel_Calculation_Functions return 64; } elseif (is_string($value)) { // Errors - if ((strlen($value) > 0) && ($value{0} == '#')) { + if ((strlen($value) > 0) && ($value[0] == '#')) { return 16; } return 2; diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell.php index c99a3c8b1..4b1437f55 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell.php @@ -809,19 +809,19 @@ class PHPExcel_Cell // We also use the language construct isset() rather than the more costly strlen() function to match the length of $pString // for improved performance - if (isset($pString{0})) { - if (!isset($pString{1})) { + if (isset($pString[0])) { + if (!isset($pString[1])) { $_indexCache[$pString] = $_columnLookup[$pString]; return $_indexCache[$pString]; - } elseif (!isset($pString{2})) { - $_indexCache[$pString] = $_columnLookup[$pString{0}] * 26 + $_columnLookup[$pString{1}]; + } elseif (!isset($pString[2])) { + $_indexCache[$pString] = $_columnLookup[$pString[0]] * 26 + $_columnLookup[$pString[1]]; return $_indexCache[$pString]; - } elseif (!isset($pString{3})) { - $_indexCache[$pString] = $_columnLookup[$pString{0}] * 676 + $_columnLookup[$pString{1}] * 26 + $_columnLookup[$pString{2}]; + } elseif (!isset($pString[3])) { + $_indexCache[$pString] = $_columnLookup[$pString[0]] * 676 + $_columnLookup[$pString[1]] * 26 + $_columnLookup[$pString[2]]; return $_indexCache[$pString]; } } - throw new PHPExcel_Exception("Column string index can not be " . ((isset($pString{0})) ? "longer than 3 characters" : "empty")); + throw new PHPExcel_Exception("Column string index can not be " . ((isset($pString[0])) ? "longer than 3 characters" : "empty")); } /** diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell/DefaultValueBinder.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell/DefaultValueBinder.php index dc19e6c45..c3e594aae 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell/DefaultValueBinder.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Cell/DefaultValueBinder.php @@ -79,15 +79,15 @@ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder return PHPExcel_Cell_DataType::TYPE_STRING; } elseif ($pValue instanceof PHPExcel_RichText) { return PHPExcel_Cell_DataType::TYPE_INLINE; - } elseif ($pValue{0} === '=' && strlen($pValue) > 1) { - return PHPExcel_Cell_DataType::TYPE_FORMULA; + } elseif (is_array($pValue) && $pValue[0] === '=' && strlen($pValue) > 1) { + return PHPExcel_Cell_DataType::TYPE_FORMULA; } elseif (is_bool($pValue)) { return PHPExcel_Cell_DataType::TYPE_BOOL; } elseif (is_float($pValue) || is_int($pValue)) { return PHPExcel_Cell_DataType::TYPE_NUMERIC; } elseif (preg_match('/^[\+\-]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)([Ee][\-\+]?[0-2]?\d{1,3})?$/', $pValue)) { $tValue = ltrim($pValue, '+-'); - if (is_string($pValue) && $tValue{0} === '0' && strlen($tValue) > 1 && $tValue{1} !== '.') { + if (is_string($pValue) && $tValue[0] === '0' && strlen($tValue) > 1 && $tValue[1] !== '.') { return PHPExcel_Cell_DataType::TYPE_STRING; } elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) { return PHPExcel_Cell_DataType::TYPE_STRING; diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/ReferenceHelper.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/ReferenceHelper.php index 7d7de93be..bdede7733 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/ReferenceHelper.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/ReferenceHelper.php @@ -881,8 +881,8 @@ class PHPExcel_ReferenceHelper list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString($pCellReference); // Verify which parts should be updated - $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && (PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn))); - $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && $newRow >= $beforeRow); + $updateColumn = (($newColumn[0] != '$') && ($beforeColumn[0] != '$') && (PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn))); + $updateRow = (($newRow[0] != '$') && ($beforeRow[0] != '$') && $newRow >= $beforeRow); // Create new column reference if ($updateColumn) { diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/String.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/String.php index fa1a64e05..10e38d20d 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/String.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Shared/String.php @@ -523,8 +523,8 @@ class PHPExcel_Shared_String if (strlen($str) < 2) { return $str; } - $c0 = ord($str{0}); - $c1 = ord($str{1}); + $c0 = ord($str[0]); + $c1 = ord($str[1]); if ($c0 == 0xfe && $c1 == 0xff) { $str = substr($str, 2); } elseif ($c0 == 0xff && $c1 == 0xfe) { @@ -535,11 +535,11 @@ class PHPExcel_Shared_String $newstr = ''; for ($i=0; $i<$len; $i+=2) { if ($bom_be) { - $val = ord($str{$i}) << 4; - $val += ord($str{$i+1}); + $val = ord($str[$i]) << 4; + $val += ord($str[$i+1]); } else { - $val = ord($str{$i+1}) << 4; - $val += ord($str{$i}); + $val = ord($str[$i+1]) << 4; + $val += ord($str[$i]); } $newstr .= ($val == 0x228) ? "\n" : chr($val); } diff --git a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Worksheet/AutoFilter.php b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Worksheet/AutoFilter.php index 6ec8a4466..1bc312bda 100644 --- a/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Worksheet/AutoFilter.php +++ b/src/vendor/phpoffice/phpexcel/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -717,7 +717,7 @@ class PHPExcel_Worksheet_AutoFilter ); } else { // Date based - if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') { + if ($dynamicRuleType[0] == 'M' || $dynamicRuleType[0] == 'Q') { // Month or Quarter sscanf($dynamicRuleType, '%[A-Z]%d', $periodType, $period); if ($periodType == 'M') { diff --git a/src/vendor/psr/http-client/CHANGELOG.md b/src/vendor/psr/http-client/CHANGELOG.md index babba7c7b..e2dc25f51 100644 --- a/src/vendor/psr/http-client/CHANGELOG.md +++ b/src/vendor/psr/http-client/CHANGELOG.md @@ -2,14 +2,6 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 1.0.3 - -Add `source` link in composer.json. No code changes. - -## 1.0.2 - -Allow PSR-7 (psr/http-message) 2.0. No code changes. - ## 1.0.1 Allow installation with PHP 8. No code changes. diff --git a/src/vendor/psr/http-client/README.md b/src/vendor/psr/http-client/README.md index 84af5c55d..6876b8403 100644 --- a/src/vendor/psr/http-client/README.md +++ b/src/vendor/psr/http-client/README.md @@ -7,6 +7,6 @@ Note that this is not a HTTP Client implementation of its own. It is merely abst The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. -[psr-url]: https://www.php-fig.org/psr/psr-18 +[psr-url]: http://www.php-fig.org/psr/psr-18 [package-url]: https://packagist.org/packages/psr/http-client [implementation-url]: https://packagist.org/providers/psr/http-client-implementation diff --git a/src/vendor/psr/http-client/composer.json b/src/vendor/psr/http-client/composer.json index 6fed350be..c195f8ff1 100644 --- a/src/vendor/psr/http-client/composer.json +++ b/src/vendor/psr/http-client/composer.json @@ -7,15 +7,12 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], - "support": { - "source": "https://github.com/php-fig/http-client" - }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" + "psr/http-message": "^1.0" }, "autoload": { "psr-4": { diff --git a/src/vendor/psr/http-factory/.pullapprove.yml b/src/vendor/psr/http-factory/.pullapprove.yml new file mode 100644 index 000000000..8cf081942 --- /dev/null +++ b/src/vendor/psr/http-factory/.pullapprove.yml @@ -0,0 +1,7 @@ +extends: default +reviewers: + - + name: contributors + required: 1 + teams: + - http-factory-contributors diff --git a/src/vendor/psr/http-factory/README.md b/src/vendor/psr/http-factory/README.md index bf8913b57..41d362a62 100644 --- a/src/vendor/psr/http-factory/README.md +++ b/src/vendor/psr/http-factory/README.md @@ -1,12 +1,10 @@ HTTP Factories ============== -This repository holds all interfaces related to [PSR-17 (HTTP Factories)][psr-url]. +This repository holds all interfaces related to [PSR-17 (HTTP Message Factories)][psr-17]. +Please refer to the specification for a description. -Note that this is not a HTTP Factory implementation of its own. It is merely interfaces that describe the components of a HTTP Factory. +You can find implementations of the specification by looking for packages providing the +[psr/http-factory-implementation](https://packagist.org/providers/psr/http-factory-implementation) virtual package. -The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. - -[psr-url]: https://www.php-fig.org/psr/psr-17/ -[package-url]: https://packagist.org/packages/psr/http-factory -[implementation-url]: https://packagist.org/providers/psr/http-factory-implementation +[psr-17]: https://www.php-fig.org/psr/psr-17/ diff --git a/src/vendor/psr/http-factory/composer.json b/src/vendor/psr/http-factory/composer.json index 82a1d3266..af62b290f 100644 --- a/src/vendor/psr/http-factory/composer.json +++ b/src/vendor/psr/http-factory/composer.json @@ -1,6 +1,6 @@ { "name": "psr/http-factory", - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ "psr", "psr-7", @@ -15,15 +15,12 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0" }, "autoload": { "psr-4": { diff --git a/src/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/src/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php index d7adbf0e2..7db4e30af 100644 --- a/src/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php +++ b/src/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php @@ -15,10 +15,10 @@ interface UploadedFileFactoryInterface * * @param StreamInterface $stream Underlying stream representing the * uploaded file content. - * @param int|null $size in bytes + * @param int $size in bytes * @param int $error PHP file upload error - * @param string|null $clientFilename Filename as provided by the client, if any. - * @param string|null $clientMediaType Media type as provided by the client, if any. + * @param string $clientFilename Filename as provided by the client, if any. + * @param string $clientMediaType Media type as provided by the client, if any. * * @return UploadedFileInterface * @@ -26,9 +26,9 @@ interface UploadedFileFactoryInterface */ public function createUploadedFile( StreamInterface $stream, - ?int $size = null, + int $size = null, int $error = \UPLOAD_ERR_OK, - ?string $clientFilename = null, - ?string $clientMediaType = null + string $clientFilename = null, + string $clientMediaType = null ): UploadedFileInterface; } diff --git a/src/vendor/psr/http-message/README.md b/src/vendor/psr/http-message/README.md index 2668be6c3..28185338f 100644 --- a/src/vendor/psr/http-message/README.md +++ b/src/vendor/psr/http-message/README.md @@ -10,7 +10,4 @@ interface that describes a HTTP message. See the specification for more details. Usage ----- -Before reading the usage guide we recommend reading the PSR-7 interfaces method list: - -* [`PSR-7 Interfaces Method List`](docs/PSR7-Interfaces.md) -* [`PSR-7 Usage Guide`](docs/PSR7-Usage.md) \ No newline at end of file +We'll certainly need some stuff in here. \ No newline at end of file diff --git a/src/vendor/psr/http-message/composer.json b/src/vendor/psr/http-message/composer.json index 56e8c0a6d..b0d2937a0 100644 --- a/src/vendor/psr/http-message/composer.json +++ b/src/vendor/psr/http-message/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.3.0" }, "autoload": { "psr-4": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } } } diff --git a/src/vendor/psr/http-message/src/MessageInterface.php b/src/vendor/psr/http-message/src/MessageInterface.php index 8cdb4ed63..dd46e5ec8 100644 --- a/src/vendor/psr/http-message/src/MessageInterface.php +++ b/src/vendor/psr/http-message/src/MessageInterface.php @@ -1,7 +1,5 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->abortMultipartUpload(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/appendObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/appendObject.php index c676fea7f..88ac65459 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/appendObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/appendObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/blindWatermark.php b/src/vendor/qcloud/cos-sdk-v5/sample/blindWatermark.php index f90301a9b..e8252a3cf 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/blindWatermark.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/blindWatermark.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $blindWatermarkTemplate = new Qcloud\Cos\ImageParamTemplate\BlindWatermarkTemplate(); $blindWatermarkTemplate->setImage("http://examplebucket-125000000.cos.ap-beijing.myqcloud.com/shuiyin.jpeg"); $blindWatermarkTemplate->setType(2); $blindWatermarkTemplate->setLevel(3); - $blindWatermarkTemplate->setVersion("2.0"); - - // -------------------- 1. 下载时处理 -------------------- // $result = $cosClient->getObject(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Key' => 'exampleobject', @@ -28,32 +25,6 @@ try { )); // 请求成功 print_r($result); - // -------------------- 1. 下载时处理 -------------------- // - - // -------------------- 2. 上传时处理 -------------------- // - $local_path = "/data/exampleobject"; - $picOperationsTemplate = new Qcloud\Cos\ImageParamTemplate\PicOperationsTransformation(); - $picOperationsTemplate->setIsPicInfo(1); - $picOperationsTemplate->addRule($blindWatermarkTemplate, "resultobject"); - $result = $cosClient->putObject(array( - 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'Key' => 'exampleobject', - 'Body' => fopen($local_path, 'rb'), - 'PicOperations' => $picOperationsTemplate->queryString(), - )); - // 请求成功 - print_r($result); - // -------------------- 2. 上传时处理 -------------------- // - - // -------------------- 3. 云上数据处理 -------------------- // - $result = $cosClient->ImageProcess(array( - 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'Key' => 'exampleobject', - 'PicOperations' => $picOperationsTemplate->queryString(), - )); - // 请求成功 - print_r($result); - // -------------------- 3. 云上数据处理 -------------------- // } catch (\Exception $e) { // 请求失败 echo($e); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/catchException.php b/src/vendor/qcloud/cos-sdk-v5/sample/catchException.php index 686432c98..0c12f5470 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/catchException.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/catchException.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketAcl(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/ciTransformation.php b/src/vendor/qcloud/cos-sdk-v5/sample/ciTransformation.php index 8b375afdb..9dbab317c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/ciTransformation.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/ciTransformation.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $imageMogrTemplate = new Qcloud\Cos\ImageParamTemplate\ImageMogrTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/completeMultipartUpload.php b/src/vendor/qcloud/cos-sdk-v5/sample/completeMultipartUpload.php index 192823f42..595036883 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/completeMultipartUpload.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/completeMultipartUpload.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->completeMultipartUpload(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/copy.php b/src/vendor/qcloud/cos-sdk-v5/sample/copy.php index 67d893699..f400dc33c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/copy.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/copy.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/copyObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/copyObject.php index 38f14c510..d58fc93c0 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/copyObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/copyObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->copyObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/cosClient.php b/src/vendor/qcloud/cos-sdk-v5/sample/cosClient.php index db178dec0..4b68d1a4a 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/cosClient.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/cosClient.php @@ -1,6 +1,6 @@ $region, //园区 - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'timeout' => 10, //超时时间 'connect_timeout' => 10, //连接超时时间 'ip' => '', //ip @@ -21,12 +21,10 @@ $cosClient = new Qcloud\Cos\Client( 'userAgent' => '', //UA 'allow_redirects' => false, //是否follow302 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey, 'token' => $token, 'anonymous' => true, //匿名模式 - ), - 'timezone' => 'PRC', //时区 - 'locationWithScheme' => true //Location中是否包含scheme + ) ) ); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createBucket.php b/src/vendor/qcloud/cos-sdk-v5/sample/createBucket.php index 98df29921..a2ed0d229 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createBucket.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createBucket.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->createBucket(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createDocProcessJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createDocProcessJobs.php index c6ed4dd63..ca8e6549f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createDocProcessJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createDocProcessJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->createDocProcessJobs(array( 'Bucket' => 'examplebucket-1250000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'DocProcess', //任务的 Tag:DocProcess 固定值 + 'QueueId' => 'pd8e422a2ea134165a92f2012ea43****', //任务所在的队列 ID 'Input' => array( 'Object' => 'Append功能测试.pdf' //待操作的文件对象 ), diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createFolder.php b/src/vendor/qcloud/cos-sdk-v5/sample/createFolder.php index f7586726b..1d3b26dd0 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createFolder.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createFolder.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaAnimationJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaAnimationJobs.php index 12a451fad..937ca20cb 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaAnimationJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaAnimationJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交动图任务 https://cloud.tencent.com/document/product/436/54001 @@ -18,6 +18,7 @@ try { $result = $cosClient->createMediaAnimationJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Animation', + 'QueueId' => 'p81e648af2aee49688xxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), @@ -28,10 +29,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'Animation.gif', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); @@ -41,6 +39,7 @@ try { $result = $cosClient->createMediaAnimationJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Animation', + 'QueueId' => 'p81e648af2aee49688xxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), @@ -69,10 +68,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'Animation.gif', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaConcatJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaConcatJobs.php index 68d6c2538..c43933871 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaConcatJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaConcatJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交拼接任务 https://cloud.tencent.com/document/product/436/54013 @@ -18,6 +18,7 @@ try { $result = $cosClient->createMediaConcatJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Concat', + 'QueueId' => 'asdadadfafsdkjhfjghdfjg', 'CallBack' => 'https://example.com/callback', 'Input' => array( 'Object' => 'video01.mp4' @@ -29,8 +30,6 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'concat-video02.mp4', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), )); // 请求成功 @@ -41,13 +40,12 @@ try { $result = $cosClient->createMediaConcatJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Concat', + 'QueueId' => 'asdadadfafsdkjhfjghdfjg', 'CallBack' => 'https://example.com/callback', 'Input' => array( 'Object' => 'video01.mp4' ), 'Operation' => array( -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 'Output' => array( 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket @@ -86,34 +84,6 @@ try { 'Height' => '', 'Fps' => '30', ), - 'AudioMixArray' => array( - array( - 'AudioSource' => '', - 'MixMode' => '', - 'Replace' => '', - 'EffectConfig' => array( - 'EnableStartFadein' => '', - 'StartFadeinTime' => '', - 'EnableEndFadeout' => '', - 'EndFadeoutTime' => '', - 'EnableBgmFade' => '', - 'BgmFadeTime' => '', - ), - ), - array( - 'AudioSource' => '', - 'MixMode' => '', - 'Replace' => '', - 'EffectConfig' => array( - 'EnableStartFadein' => '', - 'StartFadeinTime' => '', - 'EnableEndFadeout' => '', - 'EndFadeoutTime' => '', - 'EnableBgmFade' => '', - 'BgmFadeTime' => '', - ), - ), - ), ), ), )); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaJobs.php index e0a897aa0..fa282d4a4 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 多任务接口 https://cloud.tencent.com/document/product/436/58335 $result = $cosClient->CreateMediaJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Transcode', // 可选,单一任务时,优先以Operation.Tag为准,当Operation无Tag参数时,该参数生效 + 'QueueId' => 'paaf4fce5521a40888a303xxxxxxxxxxxxxx', 'CallBack' => '', 'Input' => array( 'Object' => 'example.mp4' diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSmartCoverJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSmartCoverJobs.php index c03d4355d..240ea4be7 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSmartCoverJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSmartCoverJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交智能封面任务 https://cloud.tencent.com/document/product/436/54017 $result = $cosClient->createMediaSmartCoverJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'SmartCover', + 'QueueId' => 'p81e648afxxxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), 'Operation' => array( -// 'TemplateId' => '', // 使用模版 - 'SmartCover' => array( - 'Format' => '', - 'Width' => '', - 'Height' => '', - 'Count' => '', - 'DeleteDuplicates' => '', - ), 'Output' => array( 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'SmartCover-${Number}.jpg', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', -// 'CallBackFormat' => '', -// 'CallBackType' => '', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSnapshotJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSnapshotJobs.php index 61a17d191..cab83d2a6 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSnapshotJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaSnapshotJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { - // 提交截图任务 https://cloud.tencent.com/document/product/436/76933 + // 提交截图任务 https://cloud.tencent.com/document/product/436/54005 // start --------------- 使用模版 ----------------- // $result = $cosClient->createMediaSnapshotJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Snapshot', + 'QueueId' => 'asdadadfafsdkjhfjghdfjg', 'CallBack' => 'https://example.com/callback', 'Input' => array( 'Object' => 'video01.mp4' @@ -28,16 +29,8 @@ try { 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'snapshot-${Number}.jpg', -// 'SpriteObject' => 'sprite-${Number}.jpg', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), -// 'CallBackMqConfig' => array( -// 'MqRegion' => '', -// 'MqMode' => '', -// 'MqName' => '', -// ), )); // 请求成功 print_r($result); @@ -48,6 +41,7 @@ try { $result = $cosClient->createMediaSnapshotJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Snapshot', + 'QueueId' => 'asdadadfafsdkjhfjghdfjg', 'CallBack' => 'https://example.com/callback', 'Input' => array( 'Object' => 'video01.mp4' @@ -66,8 +60,6 @@ try { 'Width' => '1280', 'Height' => '', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), )); // 请求成功 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaTranscodeJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaTranscodeJobs.php index 9a0aa6ba7..f688e9915 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaTranscodeJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaTranscodeJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交转码任务 https://cloud.tencent.com/document/product/436/54009 @@ -18,14 +18,12 @@ try { $result = $cosClient->createMediaTranscodeJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Transcode', + 'QueueId' => 'paaf4fce5521a40888a3034a5de80f6ca', 'Input' => array( 'Object' => 'example.mp4' ), 'Operation' => array( 'TemplateId' => 't04e1ab86554984f1aa17c062fbf6c007c', -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 - 'FreeTranscode' => 'true', // 闲时转码 'Output' => array( 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket @@ -72,14 +70,12 @@ try { $result = $cosClient->createMediaTranscodeJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Transcode', + 'QueueId' => 'asdadadfafsdkjhfjghdfjg', 'CallBack' => 'https://example.com/callback', 'Input' => array( 'Object' => 'video01.mp4' ), 'Operation' => array( -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 - 'FreeTranscode' => 'true', // 闲时转码 'Output' => array( 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket @@ -112,34 +108,6 @@ try { 'Start' => '0', 'Duration' => '60', ), - 'AudioMixArray' => array( - array( - 'AudioSource' => '', - 'MixMode' => '', - 'Replace' => '', - 'EffectConfig' => array( - 'EnableStartFadein' => '', - 'StartFadeinTime' => '', - 'EnableEndFadeout' => '', - 'EndFadeoutTime' => '', - 'EnableBgmFade' => '', - 'BgmFadeTime' => '', - ), - ), - array( - 'AudioSource' => '', - 'MixMode' => '', - 'Replace' => '', - 'EffectConfig' => array( - 'EnableStartFadein' => '', - 'StartFadeinTime' => '', - 'EnableEndFadeout' => '', - 'EndFadeoutTime' => '', - 'EnableBgmFade' => '', - 'BgmFadeTime' => '', - ), - ), - ), ), ), )); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoMontageJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoMontageJobs.php index e7cd4a0fd..4e62de2b2 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoMontageJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoMontageJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交精彩集锦任务 https://cloud.tencent.com/document/product/436/58337 @@ -18,6 +18,7 @@ try { $result = $cosClient->createMediaVideoMontageJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VideoMontage', + 'QueueId' => 'p81e648af2aeexxxxxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), @@ -28,10 +29,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VideoMontage.mp4', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); @@ -41,13 +39,13 @@ try { $result = $cosClient->createMediaVideoMontageJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VideoMontage', + 'QueueId' => 'p81e648af2aeexxxxxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), 'Operation' => array( 'VideoMontage' => array( 'Duration' => '', - 'Scene' => '', 'Container' => array( 'Format' => '', ), @@ -66,31 +64,13 @@ try { 'Channels' => '', 'Remove' => '', ), - 'AudioMixArray' => array( - array( - 'AudioSource' => 'https://examplebucket-125000000.cos.ap-guangzhou.myqcloud.com/test01.mp3', - 'MixMode' => 'Once', - 'Replace' => 'true', - 'EffectConfig' => array( - 'EnableStartFadein' => 'true', - 'StartFadeinTime' => '3', - 'EnableEndFadeout' => 'false', - 'EndFadeoutTime' => '0', - 'EnableBgmFade' => 'true', - 'BgmFadeTime' => '1.7', - ), - ), - ), ), 'Output' => array( 'Region' => $region, 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VideoMontage.mp4', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoProcessJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoProcessJobs.php index 9f12f3b97..4822d8fce 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoProcessJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVideoProcessJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交视频增强任务 https://cloud.tencent.com/document/product/436/60750 @@ -18,6 +18,7 @@ try { $result = $cosClient->createMediaVideoProcessJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VideoProcess', + 'QueueId' => 'p81e648afxxxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), @@ -30,10 +31,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VideoProcess.flv', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); @@ -43,6 +41,7 @@ try { $result = $cosClient->createMediaVideoProcessJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VideoProcess', + 'QueueId' => 'p81e648afxxxxxxxxxxxxxxxxx', 'Input' => array( 'Object' => 'video01.mp4' ), @@ -141,10 +140,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VideoProcess.flv', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), - 'CallBack' => '', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVoiceSeparateJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVoiceSeparateJobs.php index be9bdb8cf..a4bc42a9c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVoiceSeparateJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMediaVoiceSeparateJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 提交人声分离任务 https://cloud.tencent.com/document/product/436/58341 @@ -18,6 +18,7 @@ try { $result = $cosClient->createMediaVoiceSeparateJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VoiceSeparate', + 'QueueId' => '', 'CallBack' => '', 'Input' => array( 'Object' => 'test.mp3' @@ -29,11 +30,7 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VoiceSeparate01.mp3', 'AuObject' => 'VoiceSeparate02.mp3', - 'BassObject' => 'VoiceSeparate03.mp3', - 'DrumObject' => 'VoiceSeparate04.mp3', ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), )); // 请求成功 @@ -44,6 +41,7 @@ try { $result = $cosClient->createMediaVoiceSeparateJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'VoiceSeparate', + 'QueueId' => '', 'CallBack' => '', 'Input' => array( 'Object' => 'test.mp3' @@ -54,8 +52,6 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Object' => 'VoiceSeparate01.mp3', 'AuObject' => 'VoiceSeparate02.mp3', - 'BassObject' => 'VoiceSeparate03.mp3', - 'DrumObject' => 'VoiceSeparate04.mp3', ), 'VoiceSeparate' => array( 'AudioMode' => 'AudioAndBackground', @@ -66,8 +62,6 @@ try { 'Channels' => '2', ), ), -// 'UserData' => 'xxx', // 透传用户信息 -// 'JobLevel' => '0', // 任务优先级,级别限制:0 、1 、2。级别越大任务优先级越高,默认为0 ), )); // 请求成功 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/createMultipartUpload.php b/src/vendor/qcloud/cos-sdk-v5/sample/createMultipartUpload.php index 20d1d28e0..d81756f79 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/createMultipartUpload.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/createMultipartUpload.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->createMultipartUpload(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucket.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucket.php index dd7a1c1fb..700cb87bf 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucket.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucket.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucket(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketCors.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketCors.php index f672d22a0..c4ebd8737 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketCors.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketCors.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucketCors(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketDomain.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketDomain.php index a86259a63..cbb5ba294 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketDomain.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketDomain.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucketDomain(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketGuetzli.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketGuetzli.php index b8a4b8df3..5c00244b6 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketGuetzli.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketGuetzli.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->DeleteBucketGuetzli(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketImageStyle.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketImageStyle.php index 6c8682fda..bc403a007 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketImageStyle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketImageStyle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->DeleteBucketImageStyle(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'StyleName' => 'stylename', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketLifecycle.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketLifecycle.php index 65dc273ab..69985d703 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketLifecycle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketLifecycle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucketLifecycle(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketTagging.php index 2ce52be1e..ce6ac2357 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketTagging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucketTagging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketWebsite.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketWebsite.php index 6ba15cabc..2b6a3005f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketWebsite.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBucketWebsite.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteBucketWebsite(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBuckets.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBuckets.php index f91bcfe5e..d7f1ba1fb 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteBuckets.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteBuckets.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { //列出所有buckets diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteFolder.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteFolder.php index 30f419758..f771405f8 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteFolder.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteFolder.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $cos_path = "cos/folder"; diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteObject.php index 2e613cd15..133667c43 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/deleteObjectTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/deleteObjectTagging.php index 4b98f027e..2d1ad16de 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/deleteObjectTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/deleteObjectTagging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->deleteObjectTagging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJob.php b/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJob.php index b2aadee46..4d6d25ba3 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJob.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJob.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 查询指定的任务 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJobs.php index f24d2bf69..2e5197f4f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/describeMediaJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { /* 拉取符合条件的任务, 支持 Transcode、Snapshot、Animation、Concat、SmartCover、VideoProcess、VideoMontage、VoiceSeparate、SDRtoHDR、 - DigitalWatermark、ExtractDigitalWatermark、SuperResolution、VideoTag、PicProcess、Segment 等 + DigitalWatermark、ExtractDigitalWatermark、SuperResolution、VideoTag、PicProcess、Segment */ $result = $cosClient->describeMediaJobs(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Tag' => 'Transcode', // 任务 的Tag -// 'QueueId' => '', // queueId -// 'OrderByTime' => '', -// 'NextToken' => '', -// 'Size' => '', -// 'States' => '', -// 'StartCreationTime' => '', -// 'EndCreationTime' => '', -// 'WorkflowId' => '', -// 'InventoryTriggerJobId' => '', -// 'InputObject' => '', + 'QueueId' => 'paaf4fce5521a40888a3034a5dxxxxxxx', // queueId )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectAudio.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectAudio.php index b29020ead..5cba84f21 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectAudio.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectAudio.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // start --------------- 桶文件审核 ----------------- // @@ -19,31 +19,12 @@ try { 'Input' => array( 'Object' => 'sound01.mp3', // 'DataId' => '', // 可选 该字段在审核结果中会返回原始内容,长度限制为512字节。您可以使用该字段对待审核的数据进行唯一业务标识。 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), ), // 'Conf' => array( // 'BizType' => '', // 可选 定制化策略 // 'DetectType' => 'Porn,Terrorism,Politics,Ads', // 可选 若不传此参数,BizType为空时走默认策略,BizType不为空走定制化策略 // 'Callback' => '', // 可选 回调URL // 'CallbackVersion' => '', // 可选 回调内容的结构,有效值:Simple(回调内容包含基本信息)、Detail(回调内容包含详细信息)。默认为 Simple。 -// 'Freeze' => array( -// 'PornScore' => 90, -// 'AdsScore' => 90, -// 'PoliticsScore' => 90, -// 'TerrorismScore' => 90, -// ), // 可选 可通过该字段,设置根据审核结果给出的不同分值,对音频文件进行自动冻结,仅当`input`中审核的音频为`object`时有效 // ), // 可选 走默认策略及默认审核场景。 )); // 请求成功 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectDocument.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectDocument.php index c2a87e1b5..5d8467595 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectDocument.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectDocument.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 存储桶文档审核 @@ -20,34 +20,13 @@ try { 'Object' => 'test01.docx', // 'Type' => 'docx', // 'DataId' => '', // 选填 该字段在审核结果中会返回原始内容,长度限制为512字节。您可以使用该字段对待审核的数据进行唯一业务标识。 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), ), // 'Conf' => array( // 'BizType' => '', // 'DetectType' => 'Porn,Terrorism,Politics,Ads', // 选填,在只有BizType时走设定策略的审核场景 // 'Callback' => '', // 回调URL 选填 -// 'Freeze' => array( -// 'PornScore' => 90, -// 'AdsScore' => 90, -// 'PoliticsScore' => 90, -// 'TerrorismScore' => 90, -// ), // 选填 可通过该字段,设置根据审核结果给出的不同分值,对文档进行自动冻结。仅当`input`中审核的文档为`object`时有效。 // ), // 选填 在DetectType/BizType都不传的情况下,走默认策略及默认审核场景。 )); - // 请求成功 - print_r($result); // 文档URL审核 $result = $cosClient->detectDocument(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectImage.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectImage.php index 39507190c..58a21e92d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectImage.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectImage.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); @@ -17,13 +17,11 @@ try { $result = $cosClient->detectImage(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Key' => 'test.png', // 桶文件 + 'ci-process' => 'sensitive-content-recognition', // 'BizType' => '', // 可选 定制化策略,不传走默认策略 +// 'DetectType' => 'porn,ads', // 可选 不填走默认策略 或 定制化策略,四种参数:porn,ads等,可使用多种规则,注意规则间不要加空格 // 'Interval' => 5, // 可选 审核 GIF 时使用 截帧的间隔 // 'MaxFrames' => 5, // 可选 针对 GIF 动图审核的最大截帧数量,需大于0。 -// 'LargeImageDetect' => '', -// 'DataId' => '', -// 'Async' => '', -// 'Callback' => '', )); // 请求成功 print_r($result); @@ -31,16 +29,15 @@ try { //图片链接审核 $imgUrl = 'https://test.jpg'; - $result = $cosClient->detectImageUrl(array( + $result = $cosClient->detectImage(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket + 'Key' => '/', // 链接图片资源路径写 / 即可 + 'ci-process' => 'sensitive-content-recognition', 'DetectUrl' => $imgUrl, // 'BizType' => '', // 可选 定制化策略,不传走默认策略 +// 'DetectType' => 'porn,ads', // 可选 不填走默认策略 或 定制化策略,四种参数:porn,ads等,可使用多种规则,注意规则间不要加空格 // 'Interval' => 5, // 可选 审核 GIF 时使用 截帧的间隔 // 'MaxFrames' => 5, // 可选 针对 GIF 动图审核的最大截帧数量,需大于0。 -// 'LargeImageDetect' => '', -// 'DataId' => '', -// 'Async' => '', -// 'Callback' => '', )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectImages.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectImages.php index b031c9442..b35024a31 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectImages.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectImages.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); try { - // 获取图片base64编码 -// $localImageFile = '/tmp/test.jpg'; -// $img = file_get_contents($localImageFile); -// $imgInfo = getimagesize($localImageFile); -// $imgBase64Content = base64_encode($img); - $result = $cosClient->detectImages(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Inputs' => array( @@ -27,73 +21,18 @@ try { // 'Interval' => '', // 可选 审核 GIF 时使用 截帧的间隔 // 'MaxFrames' => '', // 可选 针对 GIF 动图审核的最大截帧数量,需大于0。 // 'DataId' => 'aaa', // 可选 图片标识,该字段在结果中返回原始内容,长度限制为512字节 -// 'LargeImageDetect' => 1, // 对于超过大小限制的图片是否进行压缩后再审核,取值为: 0(不压缩),1(压缩)。默认为0。注:压缩最大支持32M的图片,且会收取压缩费用 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), // 可选 用户业务字段 -// 'Encryption' => array( -// 'Algorithm' => '', -// 'Key' => '', -// 'IV' => '', -// 'KeyId' => '', -// 'KeyType' => 0, -// ), // 可选 文件加密信息。如果图片未做加密则不需要使用该字段,如果设置了该字段,则会按设置的信息解密后再做审核。 ), array( 'Url' => 'http://example.com/test.png', // 图片URL // 'Interval' => 5, // 可选 审核 GIF 时使用 截帧的间隔 // 'MaxFrames' => 5, // 可选 针对 GIF 动图审核的最大截帧数量,需大于0。 // 'DataId' => 'bbb', // 可选 图片标识,该字段在结果中返回原始内容,长度限制为512字节 -// 'LargeImageDetect' => 1, // 对于超过大小限制的图片是否进行压缩后再审核,取值为: 0(不压缩),1(压缩)。默认为0。注:压缩最大支持32M的图片,且会收取压缩费用 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), // 可选 用户业务字段 -// 'Encryption' => array( -// 'Algorithm' => '', -// 'Key' => '', -// 'IV' => '', -// 'KeyId' => '', -// 'KeyType' => 0, -// ), // 可选 文件加密信息。如果图片未做加密则不需要使用该字段,如果设置了该字段,则会按设置的信息解密后再做审核。 ), -// array( -// 'Content' => $imgBase64Content, // 图片文件的内容,需要先经过 base64 编码。注:Content方式提交图片不支持文件加密方式 -//// 'Interval' => 5, // 可选 审核 GIF 时使用 截帧的间隔 -//// 'MaxFrames' => 5, // 可选 针对 GIF 动图审核的最大截帧数量,需大于0。 -//// 'DataId' => 'ccc', // 可选 图片标识,该字段在结果中返回原始内容,长度限制为512字节 -// ), ), // 'Conf' => array( -// 'BizType' => '', // 可选 定制化策略,不传走默认策略 -// 'Async' => 0, // 可选 是否异步进行审核,0:同步返回结果,1:异步进行审核。默认值为 0。 -// 'Callback' => '', // 可选 审核结果(Detail版本)以回调形式发送至您的回调地址 -// 'Freeze' => array( -// 'PornScore' => 90, -// 'AdsScore' => 90, -// 'PoliticsScore' => 90, -// 'TerrorismScore' => 90, -// ), // 可选 可通过该字段,设置根据审核结果给出的不同分值,对图片进行自动冻结,仅当`input`中审核的图片为`object`时有效。 -// ) // 可选 BizType 不传的情况下,走默认策略及默认审核场景。 +// 'BizType' => '' // 可选 定制化策略,不传走默认策略 +// 'DetectType' => 'Porn,Ads', // 可选 不填走默认策略 或 定制化策略,四种参数:Porn,Ads等,可使用多种规则,注意规则间不要加空格 +// ) // 可选 在DetectType/BizType都不传的情况下,走默认策略及默认审核场景。 )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectLable.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectLable.php index d9df505c9..e0aa0563b 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectLable.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectLable.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->DetectLabel(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectText.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectText.php index 9d4549625..d8f6f1265 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectText.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectText.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // start --------------- 文本内容审核 ----------------- // @@ -42,14 +42,6 @@ try { // 'DetectType' => 'Porn,Terrorism,Politics,Ads', // 选填,在只有BizType时走设定策略的审核场景 // 'Callback' => '', // 回调URL 选填 // 'CallbackVersion' => 'Detail', // 选填 Detail、Simple 默认为 Simple -// 'Freeze' => array( -// 'PornScore' => 90, -// 'AdsScore' => 90, -// 'IllegalScore' => 90, -// 'AbuseScore' => 90, -// 'PoliticsScore' => 90, -// 'TerrorismScore' => 90, -// ), // ), // 非必选,在DetectType/BizType都不传的情况下,走默认策略及默认审核场景。 )); // 请求成功 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectVideo.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectVideo.php index 6c35911c9..5810fc696 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectVideo.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectVideo.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { //存储桶视频审核 @@ -19,26 +19,6 @@ try { 'Input' => array( 'Object' => 'test.mp4', // 存储桶文件 // 'DataId' => '', // 可选 该字段在审核结果中会返回原始内容,长度限制为512字节。您可以使用该字段对待审核的数据进行唯一业务标识。 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), -// 'Encryption' => array( -// 'Algorithm' => '', -// 'Key' => '', -// 'IV' => '', -// 'KeyId' => '', -// 'KeyType' => 0, -// ), ), 'Conf' => array( // 'BizType' => '', // 可选 定制化策略 @@ -51,16 +31,8 @@ try { // 'TimeInterval' => 50, // 可选 视频截帧频率 'Count' => '3', // 视频截帧数量 ), -// 'Freeze' => array( -// 'PornScore' => 90, -// 'AdsScore' => 90, -// 'PoliticsScore' => 90, -// 'TerrorismScore' => 90, -// ), // 可选 自动冻结配置项,可配置指定审核分数的结果进行自动冻结 ), )); - // 请求成功 - print_r($result); //视频url审核 $videoUrl = 'http://example.com/test.mp4'; @@ -83,6 +55,7 @@ try { ), ), )); + // 请求成功 print_r($result); } catch (\Exception $e) { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectVirus.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectVirus.php index 54ac7c01c..5cc3747ef 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectVirus.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectVirus.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { // 存储桶文件查毒 diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/detectWebpage.php b/src/vendor/qcloud/cos-sdk-v5/sample/detectWebpage.php index 972029e8c..cf38dbd5a 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/detectWebpage.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/detectWebpage.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); @@ -17,28 +17,13 @@ try { 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Input' => array( 'Url' => 'https://www.xxx.com/', -// 'DataId' => 'xxx', // 可选 该字段在审核结果中会返回原始内容,长度限制为512字节。您可以使用该字段对待审核的数据进行唯一业务标识。 -// 'UserInfo' => array( -// 'TokenId' => '', -// 'Nickname' => '', -// 'DeviceId' => '', -// 'AppId' => '', -// 'Room' => '', -// 'IP' => '', -// 'Type' => '', -// 'ReceiveTokenId' => '', -// 'Gender' => '', -// 'Level' => '', -// 'Role' => '', -// ), // 可选 用户业务字段 +// 'DataId' => '' // 可选 该字段在审核结果中会返回原始内容,长度限制为512字节。您可以使用该字段对待审核的数据进行唯一业务标识。 ), // 'Conf' => array( -// 'BizType' => 'd7a51676a0xxxxxxxxxxxxxxxxxxxxxx', // 可选 审核策略 -//// 'DetectType' => 'Porn', // 可选 审核的场景类型 注:该参数后续不再维护,请使用BizType参数 -// 'Callback' => 'http://xxx.com/xxx', // 可选 回调地址,以http://或者https://开头的地址。 -// 'ReturnHighlightHtml' => 'true', // 可选 true 或者 false 指定是否需要高亮展示网页内的违规文本,查询及回调结果时会根据此参数决定是否返回高亮展示的 html 内容 -// 'CallbackType' => 1, // 可选 回调片段类型,有效值:1(回调全部图片和文本片段)、2(回调违规图片和文本片段)。默认为 1。 -// ), // 审核规则配置 +//// 'DetectType' => 'Porn,Ads', // 可选 不填走默认策略 +//// 'ReturnHighlightHtml' => 'true', // 可选 'true' 或者 'false' +//// 'Callback' => '', // 可选 +// ), // 可选 在DetectType/BizType都不传的情况下,走默认策略及默认审核场景。 )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/doesBucketExist.php b/src/vendor/qcloud/cos-sdk-v5/sample/doesBucketExist.php index ca7d6f823..9c5641d7b 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/doesBucketExist.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/doesBucketExist.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->doesBucketExist( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/doesObjectExist.php b/src/vendor/qcloud/cos-sdk-v5/sample/doesObjectExist.php index 5cf3e7df8..ff297c925 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/doesObjectExist.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/doesObjectExist.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->doesObjectExist( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/download.php b/src/vendor/qcloud/cos-sdk-v5/sample/download.php index 3a6bb9038..f266e924e 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/download.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/download.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/downloadFolder.php b/src/vendor/qcloud/cos-sdk-v5/sample/downloadFolder.php index fbc06f448..db9147186 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/downloadFolder.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/downloadFolder.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey ) ) diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBlindWatermark.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBlindWatermark.php index 8e11d4dae..d300fe594 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBlindWatermark.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBlindWatermark.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { @@ -18,12 +18,9 @@ try { $blindWatermarkTemplate->setPick(); $blindWatermarkTemplate->setImage("http://examplebucket-125000000.cos.ap-beijing.myqcloud.com/shuiyin.jpeg"); $blindWatermarkTemplate->setType(2); - $blindWatermarkTemplate->setVersion("2.0"); $picOperationsTemplate = new Qcloud\Cos\ImageParamTemplate\PicOperationsTransformation(); $picOperationsTemplate->setIsPicInfo(1); $picOperationsTemplate->addRule($blindWatermarkTemplate, "resultobject"); - - // -------------------- 1. 上传时处理 -------------------- // $result = $cosClient->putObject(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Key' => 'exampleobject', @@ -32,17 +29,6 @@ try { )); // 请求成功 print_r($result); - // -------------------- 1. 上传时处理 -------------------- // - - // -------------------- 2. 云上数据处理 -------------------- // - $result = $cosClient->ImageProcess(array( - 'Bucket' => 'examplebucket-1250000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'Key' => 'exampleobject', - 'PicOperations' => $picOperationsTemplate->queryString(), - )); - // 请求成功 - print_r($result); - // -------------------- 2. 云上数据处理 -------------------- // } catch (\Exception $e) { // 请求失败 echo($e); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAccelerate.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAccelerate.php index 469b20f9f..bf4e1bc80 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAccelerate.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAccelerate.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketAccelerate(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAcl.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAcl.php index d6ee3086a..b37d93a86 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAcl.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketAcl.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketAcl(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketCors.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketCors.php index 539c4b5ac..405b63bf0 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketCors.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketCors.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketCors(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketDomain.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketDomain.php index ed30d480a..6c7479893 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketDomain.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketDomain.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketDomain(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketGuetzli.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketGuetzli.php index f434ba38e..145f3312d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketGuetzli.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketGuetzli.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->GetBucketGuetzli(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketImageStyle.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketImageStyle.php index 1f85a939e..962c79777 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketImageStyle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketImageStyle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->GetBucketImageStyle(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketInventory.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketInventory.php index b1982fa93..87e78c59f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketInventory.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketInventory.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketInvnetory(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLifecycle.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLifecycle.php index 7a5675157..055259173 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLifecycle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLifecycle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketLifecycle(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLogging.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLogging.php index 6634af082..9b5b71385 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLogging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketLogging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketLogging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketReferer.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketReferer.php index 021ef4277..48d52c5d8 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketReferer.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketReferer.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketTagging.php index 2bb65e1ee..e89a40a18 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketTagging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketTagging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketWebsite.php b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketWebsite.php index 2e1f41ebd..8a31f5b38 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getBucketWebsite.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getBucketWebsite.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getBucketWebsite(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJob.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJob.php index 6aa809fdb..fbfaf0115 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJob.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJob.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->describeDocProcessJob(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJobs.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJobs.php index 28afdcdeb..c3c53d89e 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJobs.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessJobs.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDescribeDocProcessJobs(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessQueues.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessQueues.php index dbd0006d4..4dcb4050e 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessQueues.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeDocProcessQueues.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->describeDocProcessQueues(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaBuckets.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaBuckets.php index 03360d9a5..b83d72597 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaBuckets.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaBuckets.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaQueues.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaQueues.php index e114b3840..f158406cc 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaQueues.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaQueues.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { - // https://cloud.tencent.com/document/product/436/54045 搜索媒体处理队列 $result = $cosClient->describeMediaQueues(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket -// 'QueueIds' => '', // 可选 队列 ID,以“,”符号分割字符串 -// 'Category' => 'Transcoding', // 可选 CateAll:所有类型;Transcoding:媒体处理队列;SpeedTranscoding:媒体处理倍速转码队列;默认为 Transcoding。 -// 'State' => 'Paused', // 可选 1. Active 表示队列内的作业会被媒体转码服务调度转码执行 2. Paused 表示队列暂停,作业不再会被媒体转码调度转码执行,队列内的所有作业状态维持在暂停状态,已经处于转码中的任务将继续转码,不受影响 -// 'PageNumber' => '1', // 可选 第几页 -// 'PageSize' => '2', // 可选 每页个数 + 'QueueIds' => '', // 可选 队列 ID,以“,”符号分割字符串 + 'State' => 'Paused', // 可选 1. Active 表示队列内的作业会被媒体转码服务调度转码执行 2. Paused 表示队列暂停,作业不再会被媒体转码调度转码执行,队列内的所有作业状态维持在暂停状态,已经处于转码中的任务将继续转码,不受影响 + 'PageNumber' => '1', // 可选 第几页 + 'PageSize' => '2', // 可选 每页个数 )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaVoiceSeparateJob.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaVoiceSeparateJob.php index 199bb726c..3b5fc7e2d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaVoiceSeparateJob.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDescribeMediaVoiceSeparateJob.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->describeMediaVoiceSeparateJob(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectAudioResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectAudioResult.php index da2e4752b..5c418c973 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectAudioResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectAudioResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectAudioResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectDocumentResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectDocumentResult.php index bbe326e13..6d72ada35 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectDocumentResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectDocumentResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectDocumentResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectImageResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectImageResult.php index df88cf5c2..00036ab6c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectImageResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectImageResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectImageResult(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'Key' => '', // jobId + 'Key' => 'exampleobject', // jobId )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectTextResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectTextResult.php index 6839166c3..c98fae6f3 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectTextResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectTextResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectTextResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVideoResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVideoResult.php index a713ebcfb..a4c4d7829 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVideoResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVideoResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectVideoResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVirusResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVirusResult.php index a755a9dbc..5c10a97db 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVirusResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectVirusResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectVirusResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectWebpageResult.php b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectWebpageResult.php index 0e02c5793..cd795855f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getDetectWebpageResult.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getDetectWebpageResult.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', // 审核时必须为https + 'schema' => 'https', // 审核时必须为https 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getDetectWebpageResult(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getMediaInfo.php b/src/vendor/qcloud/cos-sdk-v5/sample/getMediaInfo.php index 29d44c566..28d328e5d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getMediaInfo.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getMediaInfo.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/getObject.php index d5101d2cd..6e7afdafb 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->getObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectSensitiveContentRecognition.php b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectSensitiveContentRecognition.php index 9c9151f11..adde2bfe0 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectSensitiveContentRecognition.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectSensitiveContentRecognition.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectTagging.php index 9795806c9..8bb60239f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectTagging.php @@ -1,5 +1,5 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectUrl.php b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectUrl.php index d8467671a..823cbfa49 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectUrl.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectUrl.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectWithoutSign.php b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectWithoutSign.php index 63b20d877..bc331f593 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getObjectWithoutSign.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getObjectWithoutSign.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getPresignedUrl.php b/src/vendor/qcloud/cos-sdk-v5/sample/getPresignedUrl.php index 4fd0f3eb5..147cf6853 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getPresignedUrl.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getPresignedUrl.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $signedUrl = $cosClient->getPresignedUrl( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getPrivateM3U8.php b/src/vendor/qcloud/cos-sdk-v5/sample/getPrivateM3U8.php index 92e57c211..1dc8e6614 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getPrivateM3U8.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getPrivateM3U8.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/getSnapshot.php b/src/vendor/qcloud/cos-sdk-v5/sample/getSnapshot.php index 1ea785ef0..68d928f87 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/getSnapshot.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/getSnapshot.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $time = 3.14; $local_path = "/data/exampleobject/test.jpg"; diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/headBucket.php b/src/vendor/qcloud/cos-sdk-v5/sample/headBucket.php index 1551561be..ff1fd48eb 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/headBucket.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/headBucket.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->headBucket(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/headObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/headObject.php index 38425dd79..e5e8e8bdb 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/headObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/headObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->headObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageAve.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageAve.php index 12269c161..892bbcb9c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageAve.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageAve.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->ImageAve(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageExif.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageExif.php index 707780db6..a9973ce99 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageExif.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageExif.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->ImageExif(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageInfo.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageInfo.php index 5efa048a0..316657842 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageInfo.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageInfo.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->ImageInfo(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageMogr.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageMogr.php index 7299e4397..435c12e67 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageMogr.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageMogr.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $imageMogrTemplate = new Qcloud\Cos\ImageParamTemplate\ImageMogrTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageProcess.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageProcess.php index 69dd68d4b..0b70b7e14 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageProcess.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageProcess.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $imageMogrTemplate = new Qcloud\Cos\ImageParamTemplate\ImageMogrTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageView.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageView.php index c261e23e3..7a9873c1d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageView.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageView.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $imageViewTemplate = new Qcloud\Cos\ImageParamTemplate\ImageViewTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/imageWatermark.php b/src/vendor/qcloud/cos-sdk-v5/sample/imageWatermark.php index a7a5f905f..14a0b2329 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/imageWatermark.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/imageWatermark.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $imageWatermarkTemplate = new Qcloud\Cos\ImageParamTemplate\ImageWatermarkTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/listBuckets.php b/src/vendor/qcloud/cos-sdk-v5/sample/listBuckets.php index 17aeb1045..3ed6de2e6 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/listBuckets.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/listBuckets.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/listMultipartUploads.php b/src/vendor/qcloud/cos-sdk-v5/sample/listMultipartUploads.php index d10c66ba3..dc1050e8c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/listMultipartUploads.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/listMultipartUploads.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->listMultipartUploads(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/listObjects.php b/src/vendor/qcloud/cos-sdk-v5/sample/listObjects.php index 91a4e1a28..562a98b32 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/listObjects.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/listObjects.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->listObjects(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/listParts.php b/src/vendor/qcloud/cos-sdk-v5/sample/listParts.php index 92ada0a03..d0c1053bc 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/listParts.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/listParts.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->listParts(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/picOperations.php b/src/vendor/qcloud/cos-sdk-v5/sample/picOperations.php index 7d26e55ab..5d419b698 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/picOperations.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/picOperations.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBlindWatermark.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBlindWatermark.php index 3e5426f00..872f9a96f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBlindWatermark.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBlindWatermark.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { $blindWatermarkTemplate = new Qcloud\Cos\ImageParamTemplate\BlindWatermarkTemplate(); $blindWatermarkTemplate->setText("Test"); $blindWatermarkTemplate->setType(3); - $blindWatermarkTemplate->setVersion("2.0"); $picOperationsTemplate = new Qcloud\Cos\ImageParamTemplate\PicOperationsTransformation(); $picOperationsTemplate->setIsPicInfo(1); $picOperationsTemplate->addRule($blindWatermarkTemplate, "resultobject"); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAccelerate.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAccelerate.php index 18888c869..791631ac7 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAccelerate.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAccelerate.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketAccelerate(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAcl.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAcl.php index 7e4532181..716ac8b0b 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAcl.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketAcl.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketAcl(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketCors.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketCors.php index 6f4b4f3fb..5ae60b532 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketCors.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketCors.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketCors(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketDomain.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketDomain.php index 7bfa7410c..0431c4c8f 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketDomain.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketDomain.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketDomain(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketGuetzli.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketGuetzli.php index bf4c3208b..e7bcda47e 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketGuetzli.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketGuetzli.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->PutBucketGuetzli(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketImageStyle.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketImageStyle.php index de81bce59..4df401b08 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketImageStyle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketImageStyle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->PutBucketImageStyle(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketInventory.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketInventory.php index a5607086b..8e6f48d42 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketInventory.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketInventory.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketInventory(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLifecycle.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLifecycle.php index f0e4f57e3..8f3b96368 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLifecycle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLifecycle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketLifecycle(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLogging.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLogging.php index 6850b3795..0695959bf 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLogging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketLogging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketLogging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketReferer.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketReferer.php index fd7d4affd..1de0687c8 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketReferer.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketReferer.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials' => array( 'secretId' => $secretId, 'secretKey' => $secretKey))); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketTagging.php index 2622ee391..bf27b1e52 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketTagging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putBucketTagging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketWebsite.php b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketWebsite.php index b2521ad51..96afb2831 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putBucketWebsite.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putBucketWebsite.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putImageStyle.php b/src/vendor/qcloud/cos-sdk-v5/sample/putImageStyle.php index 2fb92af96..dfa021f0c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putImageStyle.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putImageStyle.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/putObject.php index ccfbbe717..56860c97c 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; //添加tagging diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putObjectTagging.php b/src/vendor/qcloud/cos-sdk-v5/sample/putObjectTagging.php index 0843632e8..4fe22edb0 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putObjectTagging.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putObjectTagging.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->putObjectTagging(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/putQrcode.php b/src/vendor/qcloud/cos-sdk-v5/sample/putQrcode.php index 5a0eace7e..1951adade 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/putQrcode.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/putQrcode.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; try { - // 图片上传时识别二维码 $imageQrcodeTemplate = new Qcloud\Cos\ImageParamTemplate\ImageQrcodeTemplate(); $imageQrcodeTemplate->setMode(0); $picOperationsTemplate = new Qcloud\Cos\ImageParamTemplate\PicOperationsTransformation(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/qrcode.php b/src/vendor/qcloud/cos-sdk-v5/sample/qrcode.php index d447c8046..0f354667d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/qrcode.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/qrcode.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { - // -------------------- 1. 图片二维码识别 下载时识别 -------------------- // $result = $cosClient->Qrcode(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Key' => 'exampleobject', @@ -21,27 +20,6 @@ try { )); // 请求成功 print_r($result); - // -------------------- 1. 图片二维码识别 下载时识别 -------------------- // - - // -------------------- 2. 图片二维码识别 上传时识别 -------------------- // - $imageQrcodeTemplate = new Qcloud\Cos\ImageParamTemplate\ImageQrcodeTemplate(); - $imageQrcodeTemplate->setCover(0); // 二维码覆盖功能。可为0或1,功能开启后,将对识别出的二维码覆盖上马赛克,默认值0 - $imageQrcodeTemplate->setBarType(0); // 二维码/条形码识别功能,将对识别出的二维码/条形码 覆盖马赛克。取值为0,1,2,默认值0 - $imageQrcodeTemplate->setSegment(0); // 通用的切片开关参数,指定是否需要切片,默认值0,需要切片时,后台会根据图片尺寸进行切片识别 - $imageQrcodeTemplate->setSize(100); // 当segment取值为1时生效,默认1000像素,取值范围为大于等于500的整数。当size指定的数值大于图片像素时,则不进行切片,直接识别 - - $picOperations = new Qcloud\Cos\ImageParamTemplate\PicOperationsTransformation(); - $picOperations->setIsPicInfo(1); // is_pic_info - $picOperations->addRule($imageQrcodeTemplate, "output.png"); // rules - $result = $cosClient->putObject(array( - 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket - 'Key' => 'object.jpg', - 'Body' => fopen('/tmp/local.jpg', 'rb'), // 本地文件 - 'PicOperations' => $picOperations->queryString(), - )); - // 请求成功 - print_r($result); - // -------------------- 2. 图片二维码识别 上传时识别 -------------------- // } catch (\Exception $e) { // 请求失败 echo($e); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/qrcodeGenerate.php b/src/vendor/qcloud/cos-sdk-v5/sample/qrcodeGenerate.php index ed604b1e2..16fd8d540 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/qrcodeGenerate.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/qrcodeGenerate.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { - // 二维码生成 $result = $cosClient->QrcodeGenerate(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'QrcodeContent' => '', diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/restoreObject.php b/src/vendor/qcloud/cos-sdk-v5/sample/restoreObject.php index ac6a1aadb..cfe0880ae 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/restoreObject.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/restoreObject.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->restoreObject(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/selectObjectContent.php b/src/vendor/qcloud/cos-sdk-v5/sample/selectObjectContent.php index e204c2229..c9b8de2b2 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/selectObjectContent.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/selectObjectContent.php @@ -1,15 +1,15 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey ) )); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/textWatermark.php b/src/vendor/qcloud/cos-sdk-v5/sample/textWatermark.php index ea1aa472a..f8ef0a88a 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/textWatermark.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/textWatermark.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $textWatermarkTemplate = new Qcloud\Cos\ImageParamTemplate\TextWatermarkTemplate(); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/trafficLimit.php b/src/vendor/qcloud/cos-sdk-v5/sample/trafficLimit.php index 5e20ea7b4..9bc8b1daa 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/trafficLimit.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/trafficLimit.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = '/data/exampleobject'; diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/updateMediaQueue.php b/src/vendor/qcloud/cos-sdk-v5/sample/updateMediaQueue.php index 24d1a3454..391d3e999 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/updateMediaQueue.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/updateMediaQueue.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { - // https://cloud.tencent.com/document/product/436/54046 更新媒体处理队列 $result = $cosClient->updateMediaQueue(array( 'Bucket' => 'examplebucket-125000000', //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket 'Key' => 'xxx', // queueId 'Name' => '', // 模板名称, 长度限制100字符 + 'QueueID' => 'xxx', // queueId 'State' => 'Active', // 管道状态 'NotifyConfig' => array( - 'State' => 'Off', -// 'Event' => '', -// 'ResultFormat' => '', -// 'Type' => '', -// 'Url' => '', -// 'MqMode' => '', -// 'MqRegion' => '', -// 'MqName' => '', - ), + 'Url' => '', // 回调配置 + 'Type' => 'Url', // 回调类型,普通回调:Url + 'Event' => 'TaskFinish', // 任务完成:TaskFinish;工作流完成:WorkflowFinishh + 'State' => 'Off', // 回调开关,Off,On + ), // 通知渠道 )); // 请求成功 print_r($result); diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/upload.php b/src/vendor/qcloud/cos-sdk-v5/sample/upload.php index 9a9cf13b4..1c92698f5 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/upload.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/upload.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); $local_path = "/data/exampleobject"; diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/uploadFolder.php b/src/vendor/qcloud/cos-sdk-v5/sample/uploadFolder.php index 09f87acbc..3885f7d11 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/uploadFolder.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/uploadFolder.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey ) ) diff --git a/src/vendor/qcloud/cos-sdk-v5/sample/uploadPart.php b/src/vendor/qcloud/cos-sdk-v5/sample/uploadPart.php index b915aea2b..b1709cc2d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/sample/uploadPart.php +++ b/src/vendor/qcloud/cos-sdk-v5/sample/uploadPart.php @@ -1,6 +1,6 @@ $region, - 'scheme' => 'https', //协议头部,默认为http + 'schema' => 'https', //协议头部,默认为http 'credentials'=> array( - 'secretId' => $secretId, + 'secretId' => $secretId , 'secretKey' => $secretKey))); try { $result = $cosClient->uploadPart(array( diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Client.php b/src/vendor/qcloud/cos-sdk-v5/src/Client.php index 40a1a2e68..41147f9e4 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Client.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Client.php @@ -3,7 +3,6 @@ namespace Qcloud\Cos; use GuzzleHttp\Client as HttpClient; -use GuzzleHttp\Exception\RequestException; use GuzzleHttp\HandlerStack; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -14,7 +13,6 @@ use GuzzleHttp\Command\CommandInterface; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Middleware; use GuzzleHttp\Psr7; -use GuzzleHttp\Psr7\Uri; /** * @method object AbortMultipartUpload(array $args) 舍弃一个分块上传且删除已上传的分片块 @@ -53,7 +51,7 @@ use GuzzleHttp\Psr7\Uri; * @method object PutObject(array $args) 上传对象 * @method object AppendObject(array $args) 追加对象 * @method object PutObjectAcl(array $args) 设置 COS 对象的访问权限信息(Access Control List, ACL) - * @method object PutBucketAcl(array $args) 设置存储桶(Bucket)的访问权限 (Access Control List, ACL) + * @method object PutBucketAcl(array $args) 设置存储桶(Bucket)的访问权限(Access Control List, ACL) * @method object PutBucketCors(array $args) 设置存储桶(Bucket)的跨域配置信息 * @method object PutBucketDomain(array $args) 设置存储桶(Bucket)的Domain信息 * @method object PutBucketLifecycle(array $args) 设置存储桶(Bucket)生命周期配置 @@ -115,7 +113,6 @@ use GuzzleHttp\Psr7\Uri; * @method object DescribeDocProcessJob(array $args) 查询文档转码任务 * @method object GetDescribeDocProcessJobs(array $args) 拉取符合条件的文档转码任务 * @method object DetectImage(array $args) 图片审核 - * @method object DetectImageUrl(array $args) 图片审核 * @method object DetectImages(array $args) 图片审核-批量 * @method object DetectVirus(array $args) 云查毒 * @method object GetDetectVirusResult(array $args) 查询病毒检测任务结果 @@ -132,290 +129,58 @@ use GuzzleHttp\Psr7\Uri; * @method object CreateMediaVideoProcessJobs(array $args) 提交视频增强任务 * @method object CreateMediaVideoMontageJobs(array $args) 提交精彩集锦任务 * @method object CreateMediaAnimationJobs(array $args) 提交动图任务 - * @method object CreateMediaPicProcessJobs(array $args) 提交图片处理任务 - * @method object CreateMediaSegmentJobs(array $args) 提交转封装任务 - * @method object CreateMediaVideoTagJobs(array $args) 提交视频标签任务 - * @method object CreateMediaSuperResolutionJobs(array $args) 提交超分辨率任务 - * @method object CreateMediaSDRtoHDRJobs(array $args) 提交 SDR to HDR 任务 - * @method object CreateMediaDigitalWatermarkJobs(array $args) 嵌入数字水印任务(添加水印) - * @method object CreateMediaExtractDigitalWatermarkJobs(array $args) 提取数字水印任务(提取水印) - * @method object DetectLiveVideo(array $args) 直播流审核 - * @method object CancelLiveVideoAuditing(array $args) 取消直播流审核 - * @method object OpticalOcrRecognition(array $args) 通用文字识别 - * @method object TriggerWorkflow(array $args) 手动触发工作流 - * @method object GetWorkflowInstances(array $args) 获取工作流实例列表 - * @method object GetWorkflowInstance(array $args) 获取工作流实例详情 - * @method object CreateMediaSnapshotTemplate(array $args) 新增截图模板 - * @method object UpdateMediaSnapshotTemplate(array $args) 更新截图模板 - * @method object CreateMediaTranscodeTemplate(array $args) 新增转码模板 - * @method object UpdateMediaTranscodeTemplate(array $args) 更新转码模板 - * @method object CreateMediaHighSpeedHdTemplate(array $args) 新增极速高清转码模板 - * @method object UpdateMediaHighSpeedHdTemplate(array $args) 更新极速高清转码模板 - * @method object CreateMediaAnimationTemplate(array $args) 新增动图模板 - * @method object UpdateMediaAnimationTemplate(array $args) 更新动图模板 - * @method object CreateMediaConcatTemplate(array $args) 新增拼接模板 - * @method object UpdateMediaConcatTemplate(array $args) 更新拼接模板 - * @method object CreateMediaVideoProcessTemplate(array $args) 新增视频增强模板 - * @method object UpdateMediaVideoProcessTemplate(array $args) 更新视频增强模板 - * @method object CreateMediaVideoMontageTemplate(array $args) 新增精彩集锦模板 - * @method object UpdateMediaVideoMontageTemplate(array $args) 更新精彩集锦模板 - * @method object CreateMediaVoiceSeparateTemplate(array $args) 新增人声分离模板 - * @method object UpdateMediaVoiceSeparateTemplate(array $args) 更新人声分离模板 - * @method object CreateMediaSuperResolutionTemplate(array $args) 新增超分辨率模板 - * @method object UpdateMediaSuperResolutionTemplate(array $args) 更新超分辨率模板 - * @method object CreateMediaPicProcessTemplate(array $args) 新增图片处理模板 - * @method object UpdateMediaPicProcessTemplate(array $args) 更新图片处理模板 - * @method object CreateMediaWatermarkTemplate(array $args) 新增水印模板 - * @method object UpdateMediaWatermarkTemplate(array $args) 更新水印模板 - * @method object DescribeMediaTemplates(array $args) 查询模板列表 - * @method object DescribeWorkflow(array $args) 搜索工作流 - * @method object DeleteWorkflow(array $args) 删除工作流 - * @method object CreateInventoryTriggerJob(array $args) 触发批量存量任务 - * @method object DescribeInventoryTriggerJobs(array $args) 批量拉取存量任务 - * @method object DescribeInventoryTriggerJob(array $args) 查询存量任务 - * @method object CancelInventoryTriggerJob(array $args) 取消存量任务 - * @method object CreateMediaNoiseReductionJobs(array $args) 提交音频降噪任务 - * @method object ImageRepairProcess(array $args) 图片水印修复 - * @method object ImageDetectCarProcess(array $args) 车辆车牌检测 - * @method object ImageAssessQualityProcess(array $args) 图片质量评估 - * @method object ImageSearchOpen(array $args) 开通以图搜图 - * @method object ImageSearchAdd(array $args) 添加图库图片 - * @method object ImageSearch(array $args) 图片搜索接口 - * @method object ImageSearchDelete(array $args) 图片搜索接口 - * @method object BindCiService(array $args) 绑定数据万象服务 - * @method object GetCiService(array $args) 查询数据万象服务 - * @method object UnBindCiService(array $args) 解绑数据万象服务 - * @method object GetHotLink(array $args) 查询防盗链 - * @method object AddHotLink(array $args) 查询防盗链 - * @method object OpenOriginProtect(array $args) 开通原图保护 - * @method object GetOriginProtect(array $args) 查询原图保护状态 - * @method object CloseOriginProtect(array $args) 关闭原图保护 - * @method object ImageDetectFace(array $args) 人脸检测 - * @method object ImageFaceEffect(array $args) 人脸特效 - * @method object ImageUrlFaceEffect(array $args) 人脸特效 - * @method object IDCardOCR(array $args) 身份证识别 - * @method object IDCardOCRByUpload(array $args) 身份证识别-上传时处理 - * @method object GetLiveCode(array $args) 获取数字验证码 - * @method object GetActionSequence(array $args) 获取动作顺序 - * @method object DescribeDocProcessBuckets(array $args) 查询文档预览开通状态 - * @method object UpdateDocProcessQueue(array $args) 更新文档转码队列 - * @method object CreateMediaQualityEstimateJobs(array $args) 提交视频质量评分任务 - * @method object CreateMediaStreamExtractJobs(array $args) 提交音视频流分离任务 - * @method object FileJobs4Hash(array $args) 哈希值计算同步请求 - * @method object OpenFileProcessService(array $args) 开通文件处理服务 - * @method object GetFileProcessQueueList(array $args) 搜索文件处理队列 - * @method object UpdateFileProcessQueue(array $args) 更新文件处理的队列 - * @method object CreateFileHashCodeJobs(array $args) 提交哈希值计算任务 - * @method object GetFileHashCodeResult(array $args) 查询哈希值计算结果 - * @method object CreateFileUncompressJobs(array $args) 提交文件解压任务 - * @method object GetFileUncompressResult(array $args) 查询文件解压结果 - * @method object CreateFileCompressJobs(array $args) 提交多文件打包压缩任务 - * @method object GetFileCompressResult(array $args) 查询多文件打包压缩结果 - * @method object CreateM3U8PlayListJobs(array $args) 获取指定hls/m3u8文件指定时间区间内的ts资源 - * @method object GetPicQueueList(array $args) 搜索图片处理队列 - * @method object UpdatePicQueue(array $args) 更新图片处理队列 - * @method object GetPicBucketList(array $args) 查询图片处理服务状态 - * @method object GetAiBucketList(array $args) 查询 AI 内容识别服务状态 - * @method object OpenAiService(array $args) 开通 AI 内容识别 - * @method object CloseAiService(array $args) 关闭AI内容识别服务 - * @method object GetAiQueueList(array $args) 搜索 AI 内容识别队列 - * @method object UpdateAiQueue(array $args) 更新 AI 内容识别队列 - * @method object CreateMediaTranscodeProTemplate(array $args) 创建音视频转码 pro 模板 - * @method object UpdateMediaTranscodeProTemplate(array $args) 更新音视频转码 pro 模板 - * @method object CreateVoiceTtsTemplate(array $args) 创建语音合成模板 - * @method object UpdateVoiceTtsTemplate(array $args) 更新语音合成模板 - * @method object CreateMediaSmartCoverTemplate(array $args) 创建智能封面模板 - * @method object UpdateMediaSmartCoverTemplate(array $args) 更新智能封面模板 - * @method object CreateVoiceSpeechRecognitionTemplate(array $args) 创建语音识别模板 - * @method object UpdateVoiceSpeechRecognitionTemplate(array $args) 更新语音识别模板 - * @method object CreateVoiceTtsJobs(array $args) 提交一个语音合成任务 - * @method object CreateAiTranslationJobs(array $args) 提交一个翻译任务 - * @method object CreateVoiceSpeechRecognitionJobs(array $args) 提交一个语音识别任务 - * @method object CreateAiWordsGeneralizeJobs(array $args) 提交一个分词任务 - * @method object CreateMediaVideoEnhanceJobs(array $args) 提交画质增强任务 - * @method object CreateMediaVideoEnhanceTemplate(array $args) 创建画质增强模板 - * @method object UpdateMediaVideoEnhanceTemplate(array $args) 更新画质增强模板 - * @method object OpenImageSlim(array $args) 开通图片瘦身 - * @method object CloseImageSlim(array $args) 关闭图片瘦身 - * @method object GetImageSlim(array $args) 查询图片瘦身状态 - * @method object AutoTranslationBlockProcess(array $args) 实时文字翻译 - * @method object RecognizeLogoProcess(array $args) Logo 识别 - * @method object DetectLabelProcess(array $args) 图片标签 - * @method object AIGameRecProcess(array $args) 游戏场景识别 - * @method object AIBodyRecognitionProcess(array $args) 人体识别 - * @method object DetectPetProcess(array $args) 宠物识别 - * @method object AILicenseRecProcess(array $args) 卡证识别 - * @method object CreateMediaTargetRecTemplate(array $args) 创建视频目标检测模板 - * @method object UpdateMediaTargetRecTemplate(array $args) 更新视频目标检测模板 - * @method object CreateMediaTargetRecJobs(array $args) 提交视频目标检测任务 - * @method object CreateMediaSegmentVideoBodyJobs(array $args) 提交视频人像抠图任务 - * @method object OpenAsrService(array $args) 开通智能语音服务 - * @method object GetAsrBucketList(array $args) 查询智能语音服务 - * @method object CloseAsrService(array $args) 关闭智能语音服务 - * @method object GetAsrQueueList(array $args) 查询智能语音队列 - * @method object UpdateAsrQueue(array $args) 更新智能语音队列 - * @method object CreateMediaNoiseReductionTemplate(array $args) 创建音频降噪模板 - * @method object UpdateMediaNoiseReductionTemplate(array $args) 更新音频降噪模板 - * @method object CreateVoiceSoundHoundJobs(array $args) 提交听歌识曲任务 - * @method object CreateVoiceVocalScoreJobs(array $args) 提交音乐评分任务 - * @method object CreateDataset(array $args) 创建数据集 - * @method object CreateDatasetBinding(array $args) 绑定存储桶与数据集 - * @method object CreateFileMetaIndex(array $args) 创建元数据索引 - * @method object DatasetFaceSearch(array $args) 人脸搜索 - * @method object DatasetSimpleQuery(array $args) 简单查询 - * @method object DeleteDataset(array $args) 删除数据集 - * @method object DeleteDatasetBinding(array $args) 解绑存储桶与数据集 - * @method object DeleteFileMetaIndex(array $args) 删除元数据索引 - * @method object DescribeDataset(array $args) 查询数据集 - * @method object DescribeDatasetBinding(array $args) 查询数据集与存储桶的绑定关系 - * @method object DescribeDatasetBindings(array $args) 查询绑定关系列表 - * @method object DescribeDatasets(array $args) 列出数据集 - * @method object DescribeFileMetaIndex(array $args) 查询元数据索引 - * @method object SearchImage(array $args) 图像检索 - * @method object UpdateDataset(array $args) 更新数据集 - * @method object UpdateFileMetaIndex(array $args) 更新元数据索引 - * @method object ZipFilePreview(array $args) 压缩包预览同步请求 - * @method object GetHLSPlayKey(array $args) 获取hls播放密钥 - * @method object PostWatermarkJobs(array $args) 视频明水印-提交任务 - * @method object GeneratePlayList(array $args) 生成播放列表 - * @method object CreateWatermarkTemplate(array $args) 创建明水印模板 * @see \Qcloud\Cos\Service::getService() */ class Client extends GuzzleClient { - const VERSION = '2.6.16'; + const VERSION = '2.5.5'; public $httpClient; - + private $api; private $desc; private $action; private $operation; + private $cosConfig; private $signature; private $rawCosConfig; - private $cosConfig = [ - 'scheme' => 'http', - 'region' => null, - 'credentials' => [ - 'appId' => null, - 'secretId' => '', - 'secretKey' => '', - 'anonymous' => false, - 'token' => null, - ], - 'timeout' => 3600, - 'connect_timeout' => 3600, - 'ip' => null, - 'port' => null, - 'endpoint' => null, - 'domain' => null, - 'proxy' => null, - 'retry' => 6, - 'userAgent' => 'cos-php-sdk-v5.' . Client::VERSION, - 'pathStyle' => false, - 'signHost' => true, - 'allow_redirects' => false, - 'allow_accelerate' => false, - 'timezone' => 'PRC', - 'locationWithScheme' => false, - 'autoChange' => false, - 'limit_flag' => false, - 'isCheckRequestPath' => true, - ]; - public function __construct(array $cosConfig) { $this->rawCosConfig = $cosConfig; - - $this->cosConfig = processCosConfig(array_replace_recursive($this->cosConfig, $cosConfig)); - - global $globalCosConfig; - $globalCosConfig = $this->cosConfig; + $this->cosConfig['schema'] = isset($cosConfig['schema']) ? $cosConfig['schema'] : 'http'; + $this->cosConfig['region'] = isset($cosConfig['region']) ? region_map($cosConfig['region']) : null; + $this->cosConfig['appId'] = isset($cosConfig['credentials']['appId']) ? $cosConfig['credentials']['appId'] : null; + $this->cosConfig['secretId'] = isset($cosConfig['credentials']['secretId']) ? trim($cosConfig['credentials']['secretId']) : ''; + $this->cosConfig['secretKey'] = isset($cosConfig['credentials']['secretKey']) ? trim($cosConfig['credentials']['secretKey']) : ''; + $this->cosConfig['anonymous'] = isset($cosConfig['credentials']['anonymous']) ? $cosConfig['credentials']['anonymous'] : false; + $this->cosConfig['token'] = isset($cosConfig['credentials']['token']) ? trim($cosConfig['credentials']['token']) : null; + $this->cosConfig['timeout'] = isset($cosConfig['timeout']) ? $cosConfig['timeout'] : 3600; + $this->cosConfig['connect_timeout'] = isset($cosConfig['connect_timeout']) ? $cosConfig['connect_timeout'] : 3600; + $this->cosConfig['ip'] = isset($cosConfig['ip']) ? $cosConfig['ip'] : null; + $this->cosConfig['port'] = isset($cosConfig['port']) ? $cosConfig['port'] : null; + $this->cosConfig['endpoint'] = isset($cosConfig['endpoint']) ? $cosConfig['endpoint'] : null; + $this->cosConfig['domain'] = isset($cosConfig['domain']) ? $cosConfig['domain'] : null; + $this->cosConfig['proxy'] = isset($cosConfig['proxy']) ? $cosConfig['proxy'] : null; + $this->cosConfig['retry'] = isset($cosConfig['retry']) ? $cosConfig['retry'] : 1; + $this->cosConfig['userAgent'] = isset($cosConfig['userAgent']) ? $cosConfig['userAgent'] : 'cos-php-sdk-v5.'. Client::VERSION; + $this->cosConfig['pathStyle'] = isset($cosConfig['pathStyle']) ? $cosConfig['pathStyle'] : false; + $this->cosConfig['signHost'] = isset($cosConfig['signHost']) ? $cosConfig['signHost'] : true; + $this->cosConfig['allow_redirects'] = isset($cosConfig['allow_redirects']) ? $cosConfig['allow_redirects'] : false; + $this->cosConfig['allow_accelerate'] = isset($cosConfig['allow_accelerate']) ? $cosConfig['allow_accelerate'] : false; // check config $this->inputCheck(); $service = Service::getService(); $handler = HandlerStack::create(); - - $handler->push(Middleware::retry(function ($retries, $request, $response, $exception) use (&$retryCount) { - - $this->cosConfig['limit_flag'] = false; - - $retryCount = $retries; - if ($retryCount >= $this->cosConfig['retry']) { - return false; - } - - - if ($response) { - if ($response->getStatusCode() >= 300 && !$response->hasHeader('x-cos-request-id')) { - $this->cosConfig['limit_flag'] = true; - return true; - } - - if ($response->getStatusCode() >= 500 ) { - return true; - } - } elseif ($exception) { - if ($exception instanceof Exception\ServiceResponseException) { - if ($exception->getStatusCode() >= 500) { - $this->cosConfig['limit_flag'] = true; - return true; - } - - } - if ($exception instanceof ConnectException) { - return true; - } - } - return false; - }, $this->retryDelay())); - - $handler->push(Middleware::mapRequest(function (RequestInterface $request) use (&$retryCount) { - // 获取域名 - $origin_host = $request->getUri()->getHost(); - - // 匹配 *.cos.{Region}.myqcloud.com - $pattern1 = '/\.cos\.[a-z0-9-]+\.myqcloud\.com$/'; - - if ($retryCount > 2 && $this->cosConfig['autoChange'] && $this->cosConfig['limit_flag'] && preg_match($pattern1, $origin_host)) { - $origin = $request->getUri(); - $host = str_replace("myqcloud.com", "tencentcos.cn", $origin->getHost()); - - // 将 URI 转换为字符串,然后替换主机名 - $originUriString = (string) $origin; - $originUriString = str_replace("myqcloud.com", "tencentcos.cn", $originUriString); - $originUriString = str_replace($origin->getScheme() . "://", "", $originUriString); - - // 创建新的 URI 对象 - $uri = new Uri($originUriString); - - // 获取路径,并从路径中移除主机名 - $path = $uri->getPath(); - $path = str_replace($host, '', $path); - - // 使用新的路径创建新的 URI - $uri = $uri->withPath($path); - $uri = $uri->withHost($host)->withScheme($origin->getScheme()); - - - // 更新请求的 URI 和主机头 - $request = $request->withUri($uri)->withHeader('Host', $host); - return $request; - } - return $request; - })); - + $handler->push(Middleware::retry($this->retryDecide(), $this->retryDelay())); $handler->push(Middleware::mapRequest(function (RequestInterface $request) { return $request->withHeader('User-Agent', $this->cosConfig['userAgent']); })); - if ($this->cosConfig['anonymous'] != true) { $handler->push($this::handleSignature($this->cosConfig['secretId'], $this->cosConfig['secretKey'], $this->cosConfig)); } if ($this->cosConfig['token'] != null) { $handler->push(Middleware::mapRequest(function (RequestInterface $request) { - $request = $request->withHeader('x-ci-security-token', $this->cosConfig['token']); return $request->withHeader('x-cos-security-token', $this->cosConfig['token']); })); } @@ -423,7 +188,7 @@ class Client extends GuzzleClient { $this->signature = new Signature($this->cosConfig['secretId'], $this->cosConfig['secretKey'], $this->cosConfig, $this->cosConfig['token']); $area = $this->cosConfig['allow_accelerate'] ? 'accelerate' : $this->cosConfig['region']; $this->httpClient = new HttpClient([ - 'base_uri' => "{$this->cosConfig['scheme']}://cos.{$area}.myqcloud.com/", + 'base_uri' => "{$this->cosConfig['schema']}://cos.{$area}.myqcloud.com/", 'timeout' => $this->cosConfig['timeout'], 'handler' => $handler, 'proxy' => $this->cosConfig['proxy'], @@ -432,19 +197,17 @@ class Client extends GuzzleClient { $this->desc = new Description($service); $this->api = (array) $this->desc->getOperations(); parent::__construct($this->httpClient, $this->desc, [$this, - 'commandToRequestTransformer'], [$this, 'responseToResultTransformer'], - null); + 'commandToRequestTransformer'], [$this, 'responseToResultTransformer'], + null); } - public function inputCheck() { $message = null; //检查Region if (empty($this->cosConfig['region']) && empty($this->cosConfig['domain']) && empty($this->cosConfig['endpoint']) && - empty($this->cosConfig['ip']) && - !$this->cosConfig['allow_accelerate']) { + empty($this->cosConfig['ip'])) { $message = 'Region is empty'; } //检查Secret @@ -458,6 +221,34 @@ class Client extends GuzzleClient { } } + + public function retryDecide() { + return function ( + $retries, + RequestInterface $request, + ResponseInterface $response = null, + \Exception $exception = null + ) { + if ($retries >= $this->cosConfig['retry']) { + return false; + } + if ($response != null && $response->getStatusCode() >= 400 ) { + return true; + } + if ($exception instanceof Exception\ServiceResponseException) { + if ($exception->getStatusCode() >= 400) { + return true; + } + } + + if ($exception instanceof ConnectException) { + return true; + } + + return false; + }; + } + public function retryDelay() { return function ($numberOfRetries) { return 1000 * $numberOfRetries; @@ -468,7 +259,7 @@ class Client extends GuzzleClient { { $this->action = $command->GetName(); $this->operation = $this->api[$this->action]; - $transformer = new CommandToRequestTransformer($this->cosConfig, $this->operation); + $transformer = new CommandToRequestTransformer($this->cosConfig, $this->operation); $seri = new Serializer($this->desc); $request = $seri($command); $request = $transformer->bucketStyleTransformer($command, $request); @@ -485,8 +276,7 @@ class Client extends GuzzleClient { public function responseToResultTransformer(ResponseInterface $response, RequestInterface $request, CommandInterface $command) { - - $transformer = new ResultTransformer($this->cosConfig, $this->operation); + $transformer = new ResultTransformer($this->cosConfig, $this->operation); $transformer->writeDataToLocal($command, $request, $response); $deseri = new Deserializer($this->desc, true); $result = $deseri($response, $request, $command); @@ -497,7 +287,7 @@ class Client extends GuzzleClient { $result = $transformer->ciContentInfoTransformer($command, $result); return $result; } - + public function __destruct() { } @@ -519,22 +309,8 @@ class Client extends GuzzleClient { return $this->api; } - /** - * Get the config of the cos client. - * - * @param array|string $option - * @return mixed - */ - public function getCosConfig($option = null) - { - return $option === null - ? $this->cosConfig - : (isset($this->cosConfig[$option]) ? $this->cosConfig[$option] : array()); - } - - public function setCosConfig($option, $value) - { - $this->cosConfig[$option] = $value; + private function getCosConfig() { + return $this->cosConfig; } private function createPresignedUrl(RequestInterface $request, $expires) { @@ -547,6 +323,7 @@ class Client extends GuzzleClient { return $this->createPresignedUrl($request, $expires); } + public function getObjectUrl($bucket, $key, $expires = "+30 minutes", array $args = array()) { $command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key)); $request = $this->commandToRequestTransformer($command); @@ -556,7 +333,7 @@ class Client extends GuzzleClient { public function getObjectUrlWithoutSign($bucket, $key, array $args = array()) { $command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key)); $request = $this->commandToRequestTransformer($command); - return $request->getUri()->__toString(); + return $request->getUri()-> __toString(); } public function upload($bucket, $key, $body, $options = array()) { @@ -581,29 +358,11 @@ class Client extends GuzzleClient { return $rt; } - public static function simplifyPath($path) { - $names = explode("/", $path); - $stack = array(); - foreach ($names as $name) { - if ($name == "..") { - if (!empty($stack)) { - array_pop($stack); - } - } elseif ($name && $name != ".") { - array_push($stack, $name); - } - } - return "/" . implode("/", $stack); - } - public function download($bucket, $key, $saveAs, $options = array()) { $options['PartSize'] = isset($options['PartSize']) ? $options['PartSize'] : RangeDownload::DEFAULT_PART_SIZE; + $contentLength = 0; $versionId = isset($options['VersionId']) ? $options['VersionId'] : ''; - if ($this->cosConfig['isCheckRequestPath'] && "/" == self::simplifyPath($key)) { - $e = new Exception\CosException('Getobject Key is illegal'); - $e->setExceptionCode('404'); - throw $e; - } + $rt = $this->headObject(array( 'Bucket'=>$bucket, 'Key'=>$key, @@ -711,12 +470,6 @@ class Client extends GuzzleClient { } public static function explodeKey($key) { - global $globalCosConfig; - if ($globalCosConfig['isCheckRequestPath'] && "/" == self::simplifyPath($key)) { - $e = new Exception\CosException('Getobject Key is illegal'); - $e->setExceptionCode('404'); - throw $e; - } // Remove a leading slash if one is found $split_key = explode('/', $key && $key[0] == '/' ? substr($key, 1) : $key); // Remove empty element @@ -730,6 +483,7 @@ class Client extends GuzzleClient { return $final_key; } + public static function handleSignature($secretId, $secretKey, $options) { return function (callable $handler) use ($secretId, $secretKey, $options) { return new SignatureMiddleware($handler, $secretId, $secretKey, $options); diff --git a/src/vendor/qcloud/cos-sdk-v5/src/CommandToRequestTransformer.php b/src/vendor/qcloud/cos-sdk-v5/src/CommandToRequestTransformer.php index 39ec31fe0..6c4ed461d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/CommandToRequestTransformer.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/CommandToRequestTransformer.php @@ -6,6 +6,7 @@ use Psr\Http\Message\RequestInterface; use GuzzleHttp\Command\CommandInterface; use GuzzleHttp\Psr7\Uri; use InvalidArgumentException; +use Psr\Http\Message\UriInterface; class CommandToRequestTransformer { private $config; @@ -17,34 +18,37 @@ class CommandToRequestTransformer { } // format bucket style + public function bucketStyleTransformer( CommandInterface $command, RequestInterface $request ) { $action = $command->getName(); if ($action == 'ListBuckets') { - $uri = "service.cos.myqcloud.com"; - + $uri = "service.cos.myqcloud.com"; + if ($this->config['endpoint'] != null) { $uri = $this->config['endpoint']; - } + } if ($this->config['domain'] != null) { $uri = $this->config['domain']; - } + } if ($this->config['ip'] != null) { $uri = $this->config['ip']; if ($this->config['port'] != null) { $uri = $this->config['ip'] . ":" . $this->config['port']; - } + } } - return $request->withUri(new Uri($this->config['scheme']."://". $uri. "/")); + return $request->withUri(new Uri($this->config['schema']."://". $uri. "/")); } $operation = $this->operation; $bucketname = $command['Bucket']; $appId = $this->config['appId']; - if ( $appId != null && endWith( $bucketname, '-'.$appId ) == false ) { + if ( $appId != null && endWith( $bucketname, '-'.$appId ) == False ) { $bucketname = $bucketname.'-'.$appId; } $command['Bucket'] = $bucketname; + $path = ''; + $http_method = $operation['httpMethod']; $uri = $operation['uri']; // Hoststyle is used by default @@ -65,20 +69,10 @@ class CommandToRequestTransformer { $domain_type = '.cos.'; if ($action == 'PutBucketImageStyle' || $action == 'GetBucketImageStyle' || $action == 'DeleteBucketImageStyle' - || $action == 'PutBucketGuetzli' || $action == 'GetBucketGuetzli' || $action == 'DeleteBucketGuetzli' - || $action == 'BindCiService' || $action == 'GetCiService' || $action == 'UnBindCiService' - || $action == 'GetHotLink' || $action == 'AddHotLink' - || $action == 'OpenOriginProtect' || $action == 'GetOriginProtect' || $action == 'CloseOriginProtect' - || $action == 'OpenImageSlim' || $action == 'GetImageSlim' || $action == 'CloseImageSlim') { + || $action == 'PutBucketGuetzli' || $action == 'GetBucketGuetzli' || $action == 'DeleteBucketGuetzli') { $domain_type = '.pic.'; } - if ($domain_type == '.pic.' && ($this->config['allow_accelerate'] || $this->config['region'] == 'accelerate')) { - $e = new Exception\CosException('CI request does not support using accelerate domain'); - $e->setExceptionCode('RegionUnsupport'); - throw $e; - } - $origin_host = $this->config['allow_accelerate'] ? $bucketname . $domain_type . 'accelerate' . '.' . $this->config['endpoint'] : $bucketname . $domain_type . $this->config['region'] . '.' . $this->config['endpoint']; @@ -95,11 +89,11 @@ class CommandToRequestTransformer { } } - $path = $this->config['scheme'].'://'. $host . $uri; + $path = $this->config['schema'].'://'. $host . $uri; $uri = new Uri( $path ); $query = $request->getUri()->getQuery(); if ( $uri->getQuery() != $query && $uri->getQuery() != '' ) { - $query = $uri->getQuery() . '&' . $request->getUri()->getQuery(); + $query = $uri->getQuery() . '&' . $request->getUri()->getQuery(); } $uri = $uri->withQuery( $query ); $request = $request->withUri( $uri ); @@ -108,7 +102,9 @@ class CommandToRequestTransformer { } // format upload body + public function uploadBodyTransformer( CommandInterface $command, $request, $bodyParameter = 'Body', $sourceParameter = 'SourceFile' ) { + $operation = $this->operation; if ( !isset( $operation['parameters']['Body'] ) ) { return $request; @@ -123,355 +119,202 @@ class CommandToRequestTransformer { if ( null !== $body ) { return $request; } else { - throw new InvalidArgumentException("You must specify a non-null value for the {$bodyParameter} or {$sourceParameter} parameters."); + throw new InvalidArgumentException( + "You must specify a non-null value for the {$bodyParameter} or {$sourceParameter} parameters." ); + } } - } - // update md5 - public function md5Transformer( CommandInterface $command, $request ) { - $operation = $this->operation; - if ( isset( $operation['data']['contentMd5'] ) ) { - $request = $this->addMd5( $request ); - } - if ( isset( $operation['parameters']['ContentMD5'] ) && - isset( $command['ContentMD5'] ) ) { - $value = $command['ContentMD5']; - if ( $value != false ) { + // update md5 + + public function md5Transformer( CommandInterface $command, $request ) { + $operation = $this->operation; + if ( isset( $operation['data']['contentMd5'] ) ) { $request = $this->addMd5( $request ); } - } - - return $request; - } - - // add Query string - public function queryStringTransformer( CommandInterface $command, $request ) { - $operation = $this->operation; - if ( isset( $command['Params'] ) ) { - $params = $command['Params']; - foreach ( $params as $key => $value ) { - $uri = $request->getUri(); - $query = $uri->getQuery(); - $uri = $uri->withQuery($query. "&" . urlencode($key) . "=" . $value ); - $request = $request->withUri( $uri ); - } - } - - return $request; - } - - // add Header string - public function headerTransformer( CommandInterface $command, $request ) { - $operation = $this->operation; - if ( isset( $command['Headers'] ) ) { - $headers = $command['Headers']; - foreach ( $headers as $key => $value ) { - $request = $request->withHeader( $key, $value); - } - } - return $request; - } - - // add meta - - public function metadataTransformer( CommandInterface $command, $request ) { - $operation = $this->operation; - if ( isset( $command['Metadata'] ) ) { - $meta = $command['Metadata']; - foreach ( $meta as $key => $value ) { - $request = $request->withHeader( 'x-cos-meta-' . $key, $value ); - } - } - $request = headersMap( $command, $request ); - - return $request; - } - - // count md5 - private function addMd5( $request ) { - $body = $request->getBody(); - if ( $body && $body->getSize() > 0 ) { - $md5 = base64_encode( md5( $body, true ) ); - return $request->withHeader( 'Content-MD5', $md5 ); - } - return $request; - } - - // inventoryId - public function specialParamTransformer( CommandInterface $command, $request ) { - $action = $command->getName(); - if ( $action == 'PutBucketInventory' ) { - $id = $command['Id']; - $uri = $request->getUri(); - $query = $uri->getQuery(); - $uri = $uri->withQuery( $query . '&Id='.$id ); - return $request->withUri( $uri ); - } - return $request; - } - - public function ciParamTransformer( CommandInterface $command, $request ) { - $action = $command->getName(); - if ( $action == 'GetObject' ) { - if(str_contains($uri = $request->getUri(), '%21') ) { - $uri = new Uri( str_replace('%21', '!', $uri) ); - $request = $request->withUri( $uri ); - } - if(isset($command['ImageHandleParam']) && $command['ImageHandleParam']){ - $uri = $request->getUri(); - $query = $uri->getQuery(); - if($query){ - $query .= "&" . urlencode($command['ImageHandleParam']); - }else{ - $query .= urlencode($command['ImageHandleParam']); - } - $uri = $uri->withQuery($query); - $request = $request->withUri( $uri ); - } - } - return $request; - } - - public function cosDomain2CiTransformer(CommandInterface $command, $request) { - $action = $command->getName(); - if(key_exists($action, array( - 'DescribeMediaBuckets' => 1, - 'DescribeDocProcessBuckets' => 1, - 'GetPicBucketList' => 1, - 'GetAiBucketList' => 1, - 'GetAsrBucketList' => 1, - ))) { - $origin_host = "ci.{$this->config['region']}.myqcloud.com"; - $host = $origin_host; - if ($this->config['ip'] != null) { - $host = $this->config['ip']; - if ($this->config['port'] != null) { - $host = $this->config['ip'] . ':' . $this->config['port']; + if ( isset( $operation['parameters']['ContentMD5'] ) && + isset( $command['ContentMD5'] ) ) { + $value = $command['ContentMD5']; + if ( $value != false ) { + $request = $this->addMd5( $request ); } } - // 万象接口需要https,http方式报错 - if ($this->config['scheme'] !== 'https') { - $e = new Exception\CosException('CI request scheme must be "https", instead of "http"'); - $e->setExceptionCode('Invalid Argument'); - throw $e; - } - $path = $this->config['scheme'].'://'. $host . $request->getUri()->getPath(); - $uri = new Uri( $path ); - $query = $request->getUri()->getQuery(); - $uri = $uri->withQuery( $query ); - $request = $request->withUri( $uri ); - $request = $request->withHeader( 'Host', $origin_host ); return $request; } - if(key_exists($action, array( - 'CreateDataset' => 1, - 'DeleteDataset' => 1, - 'DescribeDataset' => 1, - 'DescribeDatasets' => 1, - 'UpdateDataset' => 1, - 'CreateDatasetBinding' => 1, - 'DeleteDatasetBinding' => 1, - 'DescribeDatasetBinding' => 1, - 'DescribeDatasetBindings' => 1, - 'CreateFileMetaIndex' => 1, - 'DeleteFileMetaIndex' => 1, - 'DescribeFileMetaIndex' => 1, - 'UpdateFileMetaIndex' => 1, - 'SearchImage' => 1, - 'DatasetFaceSearch' => 1, - 'DatasetSimpleQuery' => 1, - ))) { - if (!$command->hasParam( 'AppId' )){ - $e = new Exception\CosException('params must include "Appid"'); - $e->setExceptionCode('Invalid Argument'); - throw $e; - } - $appid=$command['AppId']; - $origin_host = "$appid.ci.{$this->config['region']}.myqcloud.com"; - $host = $origin_host; - if ($this->config['ip'] != null) { - $host = $this->config['ip']; - if ($this->config['port'] != null) { - $host = $this->config['ip'] . ':' . $this->config['port']; + + // add Query string + + public function queryStringTransformer( CommandInterface $command, $request ) { + $operation = $this->operation; + if ( isset( $command['Params'] ) ) { + $params = $command['Params']; + foreach ( $params as $key => $value ) { + $uri = $request->getUri(); + $query = $uri->getQuery(); + $uri = $uri->withQuery($query. "&" . urlencode($key) . "=" . $value ); + $request = $request->withUri( $uri ); } } - // 万象接口需要https,http方式报错 - if ($this->config['scheme'] !== 'https') { - $e = new Exception\CosException('CI request scheme must be "https", instead of "http"'); - $e->setExceptionCode('Invalid Argument'); - throw $e; - } - $path = $this->config['scheme'].'://'. $host . $request->getUri()->getPath(); - $uri = new Uri( $path ); - $query = $request->getUri()->getQuery(); - $uri = $uri->withQuery( $query ); - $request = $request->withUri( $uri ); - $request = $request->withHeader( 'Host', $origin_host ); return $request; } - - $ciActions = array( - 'DetectText' => 1, - 'CreateMediaTranscodeJobs' => 1, - 'CreateMediaJobs' => 1, - 'DescribeMediaJob' => 1, - 'DescribeMediaJobs' => 1, - 'CreateMediaSnapshotJobs' => 1, - 'CreateMediaConcatJobs' => 1, - 'DetectAudio' => 1, - 'GetDetectAudioResult' => 1, - 'GetDetectTextResult' => 1, - 'DetectVideo' => 1, - 'GetDetectVideoResult' => 1, - 'DetectDocument' => 1, - 'GetDetectDocumentResult' => 1, - 'CreateDocProcessJobs' => 1, - 'DescribeDocProcessQueues' => 1, - 'DescribeDocProcessJob' => 1, - 'GetDescribeDocProcessJobs' => 1, - 'DetectImages' => 1, - 'GetDetectImageResult' => 1, - 'DetectVirus' => 1, - 'GetDetectVirusResult' => 1, - 'CreateMediaVoiceSeparateJobs' => 1, - 'DescribeMediaVoiceSeparateJob' => 1, - 'DetectWebpage' => 1, - 'GetDetectWebpageResult' => 1, - 'DescribeMediaQueues' => 1, - 'UpdateMediaQueue' => 1, - 'CreateMediaSmartCoverJobs' => 1, - 'CreateMediaVideoProcessJobs' => 1, - 'CreateMediaVideoMontageJobs' => 1, - 'CreateMediaAnimationJobs' => 1, - 'CreateMediaPicProcessJobs' => 1, - 'CreateMediaSegmentJobs' => 1, - 'CreateMediaVideoTagJobs' => 1, - 'CreateMediaSuperResolutionJobs' => 1, - 'CreateMediaSDRtoHDRJobs' => 1, - 'CreateMediaDigitalWatermarkJobs' => 1, - 'CreateMediaExtractDigitalWatermarkJobs' => 1, - 'DetectLiveVideo' => 1, - 'CancelLiveVideoAuditing' => 1, - 'TriggerWorkflow' => 1, - 'GetWorkflowInstances' => 1, - 'GetWorkflowInstance' => 1, - 'CreateMediaSnapshotTemplate' => 1, - 'UpdateMediaSnapshotTemplate' => 1, - 'CreateMediaTranscodeTemplate' => 1, - 'UpdateMediaTranscodeTemplate' => 1, - 'CreateMediaHighSpeedHdTemplate' => 1, - 'UpdateMediaHighSpeedHdTemplate' => 1, - 'CreateMediaAnimationTemplate' => 1, - 'UpdateMediaAnimationTemplate' => 1, - 'CreateMediaConcatTemplate' => 1, - 'UpdateMediaConcatTemplate' => 1, - 'CreateMediaVideoProcessTemplate' => 1, - 'UpdateMediaVideoProcessTemplate' => 1, - 'CreateMediaVideoMontageTemplate' => 1, - 'UpdateMediaVideoMontageTemplate' => 1, - 'CreateMediaVoiceSeparateTemplate' => 1, - 'UpdateMediaVoiceSeparateTemplate' => 1, - 'CreateMediaSuperResolutionTemplate' => 1, - 'UpdateMediaSuperResolutionTemplate' => 1, - 'CreateMediaPicProcessTemplate' => 1, - 'UpdateMediaPicProcessTemplate' => 1, - 'CreateMediaWatermarkTemplate' => 1, - 'UpdateMediaWatermarkTemplate' => 1, - 'DescribeMediaTemplates' => 1, - 'DescribeWorkflow' => 1, - 'DeleteWorkflow' => 1, - 'CreateInventoryTriggerJob' => 1, - 'DescribeInventoryTriggerJobs' => 1, - 'DescribeInventoryTriggerJob' => 1, - 'CancelInventoryTriggerJob' => 1, - 'CreateMediaNoiseReductionJobs' => 1, - 'ImageSearchOpen' => 1, - 'UpdateDocProcessQueue' => 1, - 'CreateMediaQualityEstimateJobs' => 1, - 'CreateMediaStreamExtractJobs' => 1, - 'OpenFileProcessService' => 1, - 'GetFileProcessQueueList' => 1, - 'UpdateFileProcessQueue' => 1, - 'CreateFileHashCodeJobs' => 1, - 'GetFileHashCodeResult' => 1, - 'CreateFileUncompressJobs' => 1, - 'GetFileUncompressResult' => 1, - 'CreateFileCompressJobs' => 1, - 'GetFileCompressResult' => 1, - 'CreateM3U8PlayListJobs' => 1, - 'GetPicQueueList' => 1, - 'UpdatePicQueue' => 1, - 'OpenAiService' => 1, - 'CloseAiService' => 1, - 'GetAiQueueList' => 1, - 'UpdateAiQueue' => 1, - 'CreateMediaTranscodeProTemplate' => 1, - 'UpdateMediaTranscodeProTemplate' => 1, - 'CreateVoiceTtsTemplate' => 1, - 'UpdateVoiceTtsTemplate' => 1, - 'CreateMediaSmartCoverTemplate' => 1, - 'UpdateMediaSmartCoverTemplate' => 1, - 'CreateVoiceSpeechRecognitionTemplate' => 1, - 'UpdateVoiceSpeechRecognitionTemplate' => 1, - 'CreateVoiceTtsJobs' => 1, - 'CreateAiTranslationJobs' => 1, - 'CreateVoiceSpeechRecognitionJobs' => 1, - 'CreateAiWordsGeneralizeJobs' => 1, - 'CreateMediaVideoEnhanceJobs' => 1, - 'CreateMediaVideoEnhanceTemplate' => 1, - 'UpdateMediaVideoEnhanceTemplate' => 1, - 'CreateMediaTargetRecTemplate' => 1, - 'UpdateMediaTargetRecTemplate' => 1, - 'CreateMediaTargetRecJobs' => 1, - 'CreateMediaSegmentVideoBodyJobs' => 1, - 'OpenAsrService' => 1, - 'CloseAsrService' => 1, - 'GetAsrQueueList' => 1, - 'UpdateAsrQueue' => 1, - 'CreateMediaNoiseReductionTemplate' => 1, - 'UpdateMediaNoiseReductionTemplate' => 1, - 'CreateVoiceSoundHoundJobs' => 1, - 'CreateVoiceVocalScoreJobs' => 1, - 'GetHLSPlayKey' => 1, - 'PostWatermarkJobs' => 1, - 'GeneratePlayList' => 1, - 'CreateWatermarkTemplate' => 1, - ); - if (key_exists($action, $ciActions)) { - // 万象接口需要https,http方式报错 - if ($this->config['scheme'] !== 'https') { - $e = new Exception\CosException('CI request scheme must be "https", instead of "http"'); - $e->setExceptionCode('Invalid Argument'); - throw $e; - } - $bucketname = $command['Bucket']; - $appId = $this->config['appId']; - if ( $appId != null && endWith( $bucketname, '-'.$appId ) == false ) { - $bucketname = $bucketname.'-'.$appId; - } - $command['Bucket'] = $bucketname; - $domain_type = '.ci.'; - $origin_host = $bucketname . $domain_type . $this->config['region'] . '.' . $this->config['endpoint']; - $host = $origin_host; - if ( $this->config['ip'] != null ) { - $host = $this->config['ip']; - if ( $this->config['port'] != null ) { - $host = $this->config['ip'] . ':' . $this->config['port']; + // add Header string + + public function headerTransformer( CommandInterface $command, $request ) { + $operation = $this->operation; + if ( isset( $command['Headers'] ) ) { + $headers = $command['Headers']; + foreach ( $headers as $key => $value ) { + $request = $request->withHeader( $key, $value); } } - $path = $this->config['scheme'].'://'. $host . $request->getUri()->getPath(); - $uri = new Uri( $path ); - $query = $request->getUri()->getQuery(); - $uri = $uri->withQuery( $query ); - $request = $request->withUri( $uri ); - $request = $request->withHeader( 'Host', $origin_host ); + return $request; + } + + // add meta + + public function metadataTransformer( CommandInterface $command, $request ) { + $operation = $this->operation; + if ( isset( $command['Metadata'] ) ) { + $meta = $command['Metadata']; + foreach ( $meta as $key => $value ) { + $request = $request->withHeader( 'x-cos-meta-' . $key, $value ); + } + } + $request = headersMap( $command, $request ); + + return $request; + } + + // count md5 + + private function addMd5( $request ) { + $body = $request->getBody(); + if ( $body && $body->getSize() > 0 ) { + $md5 = base64_encode( md5( $body, true ) ); + return $request->withHeader( 'Content-MD5', $md5 ); + } + return $request; + } + + // inventoryId + + public function specialParamTransformer( CommandInterface $command, $request ) { + $action = $command->getName(); + if ( $action == 'PutBucketInventory' ) { + $id = $command['Id']; + $uri = $request->getUri(); + $query = $uri->getQuery(); + $uri = $uri->withQuery( $query . '&Id='.$id ); + return $request->withUri( $uri ); + } + return $request; + } + + public function ciParamTransformer( CommandInterface $command, $request ) { + $action = $command->getName(); + if ( $action == 'GetObject' ) { + if(str_contains($uri = $request->getUri(), '%21') ) { + $uri = new Uri( str_replace('%21', '!', $uri) ); + $request = $request->withUri( $uri ); + } + if(isset($command['ImageHandleParam']) && $command['ImageHandleParam']){ + $uri = $request->getUri(); + $query = $uri->getQuery(); + if($query){ + $query .= "&" . urlencode($command['ImageHandleParam']); + }else{ + $query .= urlencode($command['ImageHandleParam']); + } + $uri = $uri->withQuery($query); + $request = $request->withUri( $uri ); + } + } + return $request; + } + + public function cosDomain2CiTransformer(CommandInterface $command, $request) { + $action = $command->getName(); + if(key_exists($action, array( 'DescribeMediaBuckets' => 1, ))) { + $origin_host = "ci.{$this->config['region']}.myqcloud.com"; + $host = $origin_host; + if ($this->config['ip'] != null) { + $host = $this->config['ip']; + if ($this->config['port'] != null) { + $host = $this->config['ip'] . ":" . $this->config['port']; + } + } + + $path = $this->config['schema'].'://'. $host . $request->getUri()->getPath(); + $uri = new Uri( $path ); + $query = $request->getUri()->getQuery(); + $uri = $uri->withQuery( $query ); + $request = $request->withUri( $uri ); + $request = $request->withHeader( 'Host', $origin_host ); + return $request; + } + $ciActions = array( + 'DetectText' => 1, + 'CreateMediaTranscodeJobs' => 1, + 'CreateMediaJobs' => 1, + 'DescribeMediaJob' => 1, + 'DescribeMediaJobs' => 1, + 'CreateMediaSnapshotJobs' => 1, + 'CreateMediaConcatJobs' => 1, + 'DetectAudio' => 1, + 'GetDetectAudioResult' => 1, + 'GetDetectTextResult' => 1, + 'DetectVideo' => 1, + 'GetDetectVideoResult' => 1, + 'DetectDocument' => 1, + 'GetDetectDocumentResult' => 1, + 'CreateDocProcessJobs' => 1, + 'DescribeDocProcessQueues' => 1, + 'DescribeDocProcessJob' => 1, + 'GetDescribeDocProcessJobs' => 1, + 'DetectImages' => 1, + 'GetDetectImageResult' => 1, + 'DetectVirus' => 1, + 'GetDetectVirusResult' => 1, + 'CreateMediaVoiceSeparateJobs' => 1, + 'DescribeMediaVoiceSeparateJob' => 1, + 'DetectWebpage' => 1, + 'GetDetectWebpageResult' => 1, + 'DescribeMediaQueues' => 1, + 'UpdateMediaQueue' => 1, + 'CreateMediaSmartCoverJobs' => 1, + 'CreateMediaVideoProcessJobs' => 1, + 'CreateMediaVideoMontageJobs' => 1, + 'CreateMediaAnimationJobs' => 1, + ); + if (key_exists($action, $ciActions)) { + $bucketname = $command['Bucket']; + $appId = $this->config['appId']; + if ( $appId != null && endWith( $bucketname, '-'.$appId ) == False ) { + $bucketname = $bucketname.'-'.$appId; + } + $command['Bucket'] = $bucketname; + $domain_type = '.ci.'; + $origin_host = $bucketname . $domain_type . $this->config['region'] . '.' . $this->config['endpoint']; + $host = $origin_host; + if ( $this->config['ip'] != null ) { + $host = $this->config['ip']; + if ( $this->config['port'] != null ) { + $host = $this->config['ip'] . ':' . $this->config['port']; + } + } + $path = $this->config['schema'].'://'. $host . $request->getUri()->getPath(); + $uri = new Uri( $path ); + $query = $request->getUri()->getQuery(); + $uri = $uri->withQuery( $query ); + $request = $request->withUri( $uri ); + $request = $request->withHeader( 'Host', $origin_host ); + } + return $request; + } + + public function __destruct() { } - return $request; - } - public function __destruct() { } -} diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Common.php b/src/vendor/qcloud/cos-sdk-v5/src/Common.php index 1ba697a18..1cc324640 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Common.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Common.php @@ -24,29 +24,6 @@ function region_map($region) return $region; } -function processCosConfig($config) -{ - $config['region'] = !empty($config['region']) ? region_map($config['region']) : $config['region']; - $config['secretId'] = trim($config['credentials']['secretId']); - $config['secretKey'] = trim($config['credentials']['secretKey']); - $config['token'] = !empty($config['credentials']['token']) ? trim($config['credentials']['token']) : $config['credentials']['token']; - $config['appId'] = $config['credentials']['appId']; - $config['anonymous'] = $config['credentials']['anonymous']; - unset($config['credentials']); - - if (isset($config['schema'])) { - $config['scheme'] = $config['schema']; - unset($config['schema']); - } - - if (isset($config['locationWithSchema'])) { - $config['locationWithScheme'] = $config['locationWithSchema']; - unset($config['locationWithSchema']); - } - - return $config; -} - function encodeKey($key) { return str_replace('%2F', '/', rawurlencode($key)); diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Copy.php b/src/vendor/qcloud/cos-sdk-v5/src/Copy.php index 23c887ced..18b3d0356 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Copy.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Copy.php @@ -18,8 +18,6 @@ class Copy { private $size; private $commandList = []; private $requestList = []; - private $concurrency; - private $retry; public function __construct($client, $source, $options = array()) { $minPartSize = $options['PartSize']; @@ -110,7 +108,7 @@ class Copy { $this->parts[$index] = $part; } catch(\Exception $e) { if ($i == $retry) { - throw $e; + throw($e); } } } @@ -138,4 +136,5 @@ class Copy { $result = $this->client->createMultipartUpload($this->options); return $result['UploadId']; } + } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Descriptions.php b/src/vendor/qcloud/cos-sdk-v5/src/Descriptions.php index 487de0954..3014f18c6 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Descriptions.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Descriptions.php @@ -27,28 +27,24 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'Tag' => array('location' => 'xml', 'type' => 'string', ), 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'FreeTranscode' => array( 'type' => 'string', 'location' => 'xml', ), 'WatermarkTemplateId' => array( 'type' => 'array', 'location' => 'xml', @@ -71,13 +67,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ), 'Video' => array( @@ -146,56 +135,6 @@ class Descriptions { ), ), ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), ), ), 'Watermark' => array( @@ -253,70 +192,15 @@ class Descriptions { ), ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Subtitles' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Subtitle' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'Subtitle', - 'sentAs' => 'Subtitle', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Embed' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'OutlineColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'VMargin' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'CallBackKafkaConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'InstanceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Topic' => array( 'type' => 'string', 'location' => 'xml', ), ), ), ), @@ -367,19 +251,19 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'array', 'location' => 'xml', 'data' => array( @@ -392,8 +276,6 @@ class Descriptions { 'properties' => array( 'Tag' => array('location' => 'xml', 'type' => 'string', ), 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'TranscodeTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), 'VideoProcess' => array( 'type' => 'object', @@ -706,15 +588,6 @@ class Descriptions { ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -814,11 +687,13 @@ class Descriptions { 'location' => 'uri', ), 'Tag' => array( + 'required' => true, 'type' => 'string', 'location' => 'query', 'sentAs' => 'tag', ), 'QueueId' => array( + 'required' => true, 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueId', @@ -853,9 +728,6 @@ class Descriptions { 'location' => 'query', 'sentAs' => 'endCreationTime', ), - 'WorkflowId' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'workflowId', ), - 'InventoryTriggerJobId' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'inventoryTriggerJobId', ), - 'InputObject' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'inputObject', ), ), ); } @@ -903,31 +775,31 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpriteObject' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Snapshot' => array( @@ -942,17 +814,6 @@ class Descriptions { 'Height' => array( 'type' => 'string', 'location' => 'xml', ), ), ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), ), ), ), @@ -1003,32 +864,31 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), // 拼接任务Input可以为空,完全用数组内的元素拼接 + 'Object' => array( 'required' =>false, 'type' => 'string', 'location' => 'xml', ), // 拼接任务Input可以为空,完全用数组内的元素拼接 ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'ConcatTemplate' => array( @@ -1061,7 +921,6 @@ class Descriptions { 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'FragmentIndex' => array( 'type' => 'string', 'location' => 'xml', ), // 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), 拼接接口不需要Mode参数 ), ), @@ -1085,69 +944,10 @@ class Descriptions { 'Format' => array( 'type' => 'string', 'location' => 'xml', ), ), ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -1216,23 +1016,6 @@ class Descriptions { 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ), 'Conf' => array( @@ -1255,20 +1038,6 @@ class Descriptions { 'type' => 'string', 'location' => 'xml', ), - 'CallbackType' => array( - 'type' => 'integer', - 'location' => 'xml', - ), - 'Freeze' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'PornScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AdsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PoliticsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TerrorismScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -1352,11 +1121,7 @@ class Descriptions { 'Object' => array( 'type' => 'string', 'location' => 'xml', ), 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), 'Result' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ForbidState' => array( 'type' => 'integer', 'location' => 'xml', ), 'AudioText' => array( 'type' => 'string', 'location' => 'xml', ), 'PornInfo' => array( 'type' => 'object', @@ -1365,8 +1130,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), ), ), 'TerrorismInfo' => array( @@ -1376,8 +1139,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), ), ), 'PoliticsInfo' => array( @@ -1387,8 +1148,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), ), ), 'AdsInfo' => array( @@ -1398,19 +1157,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TeenagerInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), ), ), 'Section' => array( @@ -1421,69 +1167,19 @@ class Descriptions { 'properties' => array( 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OffsetTime' => array( 'type' => 'integer', 'location' => 'xml', ), 'Duration' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Result' => array( 'type' => 'integer', 'location' => 'xml', ), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', 'properties' => array( 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array( 'type' => 'string', 'location' => 'xml', ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - 'SpeakerResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - 'RecognitionResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -1492,58 +1188,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array( 'type' => 'string', 'location' => 'xml', ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - 'SpeakerResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - 'RecognitionResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -1552,58 +1201,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array( 'type' => 'string', 'location' => 'xml', ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - 'SpeakerResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - 'RecognitionResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -1612,177 +1214,16 @@ class Descriptions { 'properties' => array( 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array( 'type' => 'string', 'location' => 'xml', ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - 'SpeakerResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - 'RecognitionResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'TeenagerInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - 'SpeakerResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - 'RecognitionResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'LanguageResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'StartTime' => array( 'type' => 'integer', 'location' => 'xml',), - 'EndTime' => array( 'type' => 'integer', 'location' => 'xml',), - ), ), ), ), ), ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'CosHeaders' => array( - 'type' => 'object', - 'location' => 'xml', - ), ), ), ), @@ -1845,9 +1286,7 @@ class Descriptions { 'Content' => array( 'type' => 'string', 'location' => 'xml', ), 'SectionCount' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'Result' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ForbidState' => array( 'type' => 'integer', 'location' => 'xml', ), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', @@ -1912,24 +1351,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -1939,24 +1360,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -1966,24 +1369,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -1993,24 +1378,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'IllegalInfo' => array( @@ -2020,24 +1387,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'AbuseInfo' => array( @@ -2047,60 +1396,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Keywords' => array( 'type' => 'string', 'location' => 'xml', ), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), ), ), ), @@ -2137,34 +1432,6 @@ class Descriptions { 'Object' => array( 'type' => 'string', 'location' => 'xml', ), 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Encryption' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Algorithm' => array( 'type' => 'string', 'location' => 'xml', ), - 'Key' => array( 'type' => 'string', 'location' => 'xml', ), - 'IV' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeyId' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeyType' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), 'Conf' => array( @@ -2176,26 +1443,15 @@ class Descriptions { 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), 'CallbackVersion' => array( 'type' => 'string', 'location' => 'xml', ), 'DetectContent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CallbackType' => array( 'type' => 'integer', 'location' => 'xml', ), 'Snapshot' => array( 'location' => 'xml', 'type' => 'object', 'properties' => array( 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'integer', 'location' => 'xml', ), + 'Count' => array( 'type' => 'string', 'location' => 'xml', ), 'TimeInterval' => array( 'type' => 'numeric', 'location' => 'xml', ), ), ), - 'Freeze' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'PornScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AdsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PoliticsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TerrorismScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -2280,7 +1536,6 @@ class Descriptions { 'SnapshotCount' => array('type' => 'string', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), 'Result' => array('type' => 'integer', 'location' => 'xml',), - 'ForbidState' => array('type' => 'integer', 'location' => 'xml',), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', @@ -2330,9 +1585,6 @@ class Descriptions { 'Url' => array('type' => 'string', 'location' => 'xml',), 'SnapshotTime' => array('type' => 'integer', 'location' => 'xml',), 'Text' => array('type' => 'string', 'location' => 'xml',), - 'Label' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), - 'Result' => array('type' => 'integer', 'location' => 'xml',), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', @@ -2340,7 +1592,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -2350,7 +1601,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'integer', 'location' => 'xml',), - 'SubLabel' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -2378,7 +1628,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -2393,18 +1642,6 @@ class Descriptions { ) ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ) ), 'TerrorismInfo' => array( @@ -2414,7 +1651,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -2424,7 +1660,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'integer', 'location' => 'xml',), - 'SubLabel' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -2452,7 +1687,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -2467,18 +1701,6 @@ class Descriptions { ) ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ) ), 'PoliticsInfo' => array( @@ -2488,7 +1710,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -2498,7 +1719,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'integer', 'location' => 'xml',), - 'SubLabel' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -2526,7 +1746,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -2541,18 +1760,6 @@ class Descriptions { ) ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ) ), 'AdsInfo' => array( @@ -2562,7 +1769,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -2572,7 +1778,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'integer', 'location' => 'xml',), - 'SubLabel' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -2600,7 +1805,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -2615,18 +1819,6 @@ class Descriptions { ) ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ) ), 'TeenagerInfo' => array( @@ -2636,7 +1828,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -2646,7 +1837,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'integer', 'location' => 'xml',), - 'SubLabel' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -2674,7 +1864,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -2689,18 +1878,6 @@ class Descriptions { ) ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ) ), ) @@ -2717,7 +1894,6 @@ class Descriptions { 'OffsetTime' => array('type' => 'integer', 'location' => 'xml',), 'Duration' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Result' => array('type' => 'integer', 'location' => 'xml',), 'PornInfo' => array( 'type' => 'object', @@ -2725,30 +1901,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array('type' => 'string', 'location' => 'xml',), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ) ), 'TerrorismInfo' => array( @@ -2757,30 +1914,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array('type' => 'string', 'location' => 'xml',), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ) ), 'PoliticsInfo' => array( @@ -2789,30 +1927,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array('type' => 'string', 'location' => 'xml',), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ) ), 'AdsInfo' => array( @@ -2821,30 +1940,11 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array('type' => 'string', 'location' => 'xml',), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ) ), 'TeenagerInfo' => array( @@ -2853,71 +1953,16 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', 'items' => array('type' => 'string', 'location' => 'xml',), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ) ), ), ), ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), ) ), 'NonExistJobIds' => array('type' => 'string', 'location' => 'xml',) @@ -2951,23 +1996,6 @@ class Descriptions { 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'Type' => array( 'type' => 'string', 'location' => 'xml', ), 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ), 'Conf' => array( @@ -2977,17 +2005,6 @@ class Descriptions { 'DetectType' => array( 'type' => 'string', 'location' => 'xml', ), 'Callback' => array( 'type' => 'string', 'location' => 'xml', ), 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallbackType' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Freeze' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'PornScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AdsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PoliticsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TerrorismScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -3072,7 +2089,6 @@ class Descriptions { 'Object' => array('type' => 'string', 'location' => 'xml',), 'Url' => array('type' => 'string', 'location' => 'xml',), 'PageCount' => array('type' => 'integer', 'location' => 'xml',), - 'ForbidState' => array('type' => 'integer', 'location' => 'xml',), 'Labels' => array( 'type' => 'object', 'location' => 'xml', @@ -3133,7 +2149,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'OcrResults' => array( @@ -3144,7 +2159,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -3172,7 +2186,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -3187,18 +2200,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -3206,7 +2207,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'OcrResults' => array( @@ -3217,7 +2217,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -3245,7 +2244,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -3260,18 +2258,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -3279,7 +2265,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'OcrResults' => array( @@ -3290,7 +2275,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -3318,7 +2302,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -3333,18 +2316,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -3352,7 +2323,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'OcrResults' => array( @@ -3363,7 +2333,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -3391,7 +2360,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array('type' => 'string', 'location' => 'xml',), - 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -3406,18 +2374,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), ), @@ -3425,42 +2381,6 @@ class Descriptions { ), ), ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), ), ), ), @@ -3485,56 +2405,82 @@ class Descriptions { 'location' => 'uri', ), 'Tag' => array( + 'required' => true, 'type' => 'string', 'location' => 'xml', ), 'QueueId' => array( + 'required' => true, 'type' => 'string', 'location' => 'xml', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'Region' => array( - 'type' => 'string','location' => 'xml', + 'type' => 'string','required' => true,'location' => 'xml', ), 'Bucket' => array( - 'type' => 'string','location' => 'xml', + 'type' => 'string','required' => true,'location' => 'xml', ), 'Object' => array( - 'type' => 'string','location' => 'xml', + 'type' => 'string','required' => true,'location' => 'xml', ), ), ), 'DocProcess' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'SrcType' => array( 'type' => 'string', 'location' => 'xml', ), - 'TgtType' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartPage' => array( 'type' => 'integer', 'location' => 'xml', ), - 'EndPage' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SheetId' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PaperDirection' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PaperSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ImageParams' => array( 'type' => 'string', 'location' => 'xml', ), - 'Quality' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Zoom' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ImageDpi' => array( 'type' => 'integer', 'location' => 'xml', ), - 'DocPassword' => array( 'type' => 'string', 'location' => 'xml', ), - 'Comments' => array( 'type' => 'integer', 'location' => 'xml', ), + 'SrcType' => array( + 'type' => 'string', + ), + 'TgtType' => array( + 'type' => 'string', + ), + 'SheetId' => array( + 'type' => 'integer', + ), + 'StartPage' => array( + 'type' => 'integer', + ), + 'EndPage' => array( + 'type' => 'integer', + ), + 'ImageParams' => array( + 'type' => 'string', + ), + 'DocPassword' => array( + 'type' => 'string', + ), + 'Comments' => array( + 'type' => 'integer', + ), + 'PaperDirection' => array( + 'type' => 'integer', + ), + 'Quality' => array( + 'type' => 'integer', + ), + 'Zoom' => array( + 'type' => 'integer', + ), ), ), ), @@ -3739,6 +2685,11 @@ class Descriptions { 'type' => 'object', 'additionalProperties' => true, 'properties' => array( + 'Body' => array( + 'type' => 'string', + 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', + 'location' => 'body', + ), 'RequestId' => array( 'type' => 'string', 'location' => 'header', @@ -3793,56 +2744,55 @@ class Descriptions { ), ), 'Operation' => array( - 'type' => 'object', + 'type' => 'array', 'location' => 'xml', - 'properties' => array( - 'DocProcess' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SrcType' => array( - 'type' => 'string', - ), - 'TgtType' => array( - 'type' => 'string', - ), - 'SheetId' => array( - 'type' => 'integer', - ), - 'StartPage' => array( - 'type' => 'integer', - ), - 'EndPage' => array( - 'type' => 'integer', - ), - 'ImageParams' => array( - 'type' => 'string', - ), - 'DocPassword' => array( - 'type' => 'string', - ), - 'Comments' => array( - 'type' => 'integer', - ), - 'PaperDirection' => array( - 'type' => 'integer', - ), - 'Quality' => array( - 'type' => 'integer', - ), - 'Zoom' => array( - 'type' => 'integer', + 'items' => array( + 'type' => 'object', + 'properties' => array( + 'DocProcess' => array( + 'type' => 'object', + 'location' => 'xml', + 'properties' => array( + 'SrcType' => array( + 'type' => 'string', + ), + 'TgtType' => array( + 'type' => 'string', + ), + 'SheetId' => array( + 'type' => 'integer', + ), + 'StartPage' => array( + 'type' => 'integer', + ), + 'EndPage' => array( + 'type' => 'integer', + ), + 'ImageParams' => array( + 'type' => 'string', + ), + 'DocPassword' => array( + 'type' => 'string', + ), + 'Comments' => array( + 'type' => 'integer', + ), + 'PaperDirection' => array( + 'type' => 'integer', + ), + 'Quality' => array( + 'type' => 'integer', + ), + 'Zoom' => array( + 'type' => 'integer', + ), ), ), - ), - 'DocProcessResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'PageInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( + 'DocProcessResult' => array( + 'type' => 'object', + 'location' => 'xml', + 'properties' => array( + 'PageInfo' => array( 'type' => 'object', 'location' => 'xml', 'properties' => array( @@ -3863,39 +2813,39 @@ class Descriptions { ), ), ), - ), - 'SuccPageCount' => array( - 'type' => 'integer', - ), - 'FailPageCount' => array( - 'type' => 'integer', - ), - 'TaskId' => array( - 'type' => 'string', - ), - 'TgtType' => array( - 'type' => 'string', - ), - 'TotalPageCount' => array( - 'type' => 'integer', - ), - 'TotalSheetCount' => array( - 'type' => 'integer', + 'SuccPageCount' => array( + 'type' => 'integer', + ), + 'FailPageCount' => array( + 'type' => 'integer', + ), + 'TaskId' => array( + 'type' => 'string', + ), + 'TgtType' => array( + 'type' => 'string', + ), + 'TotalPageCount' => array( + 'type' => 'integer', + ), + 'TotalSheetCount' => array( + 'type' => 'integer', + ), ), ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Bucket' => array( - 'type' => 'string', - ), - 'Object' => array( - 'type' => 'string', - ), - 'Region' => array( - 'type' => 'string', + 'Output' => array( + 'type' => 'object', + 'location' => 'xml', + 'properties' => array( + 'Bucket' => array( + 'type' => 'string', + ), + 'Object' => array( + 'type' => 'string', + ), + 'Region' => array( + 'type' => 'string', + ), ), ), ), @@ -3921,11 +2871,13 @@ class Descriptions { 'location' => 'uri', ), 'Tag' => array( + 'required' => true, 'type' => 'string', 'location' => 'query', 'sentAs' => 'tag', ), 'QueueId' => array( + 'required' => true, 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueId', @@ -4067,7 +3019,7 @@ class Descriptions { public static function DetectImage() { return array( 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=sensitive-content-recognition', + 'uri' => '/{Bucket}{/Key*}', 'class' => 'Qcloud\\Cos\\Command', 'responseClass' => 'DetectImageOutput', 'responseType' => 'model', @@ -4086,67 +3038,10 @@ class Descriptions { 'Qcloud\\Cos\\Client::explodeKey' ) ), - 'DetectType' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'detect-type' - ), - 'DetectUrl' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'detect-url' - ), - 'Interval' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'interval' - ), - 'MaxFrames' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'max-frames' - ), - 'BizType' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'biz-type' - ), - 'LargeImageDetect' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'large-image-detect' - ), - 'DataId' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'dataid' - ), - 'Async' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'async' - ), - 'Callback' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'callback' - ), - ), - ); - } - - public static function DetectImageUrl() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?ci-process=sensitive-content-recognition', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DetectImageOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( + 'ci-process' => array( 'required' => true, 'type' => 'string', - 'location' => 'uri', + 'location' => 'query' ), 'DetectType' => array( 'type' => 'string', @@ -4172,27 +3067,7 @@ class Descriptions { 'type' => 'string', 'location' => 'query', 'sentAs' => 'biz-type' - ), - 'LargeImageDetect' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'large-image-detect' - ), - 'DataId' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'dataid' - ), - 'Async' => array( - 'type' => 'integer', - 'location' => 'query', - 'sentAs' => 'async' - ), - 'Callback' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'callback' - ), + ) ), ); } @@ -4207,13 +3082,11 @@ class Descriptions { 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), 'Result' => array('type' => 'integer', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'JobId' => array('type' => 'string', 'location' => 'xml',), 'CompressionResult' => array('type' => 'integer', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Text' => array('type' => 'string', 'location' => 'xml',), - 'DataId' => array('type' => 'string', 'location' => 'xml',), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', @@ -4223,7 +3096,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4233,7 +3105,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4261,7 +3132,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4276,18 +3146,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerroristInfo' => array( @@ -4299,7 +3157,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4309,7 +3166,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4337,7 +3193,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4352,18 +3207,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -4375,7 +3218,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4385,7 +3227,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4413,7 +3254,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4428,18 +3268,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -4451,7 +3279,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4461,7 +3288,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4489,7 +3315,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4504,18 +3329,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -4527,7 +3340,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4537,7 +3349,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4565,7 +3376,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4580,18 +3390,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TeenagerInfo' => array( @@ -4603,7 +3401,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4613,7 +3410,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4641,7 +3437,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4656,94 +3451,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'QualityInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'integer', 'location' => 'xml',), - 'Msg' => array( 'type' => 'string', 'location' => 'xml',), - 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'OcrResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Width' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Height' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Rotate' => array( 'type' => 'numeric', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'ObjectResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Width' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Height' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Rotate' => array( 'type' => 'numeric', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), ) @@ -4782,39 +3489,9 @@ class Descriptions { 'properties' => array( 'Object' => array( 'type' => 'string', 'location' => 'xml', ), 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Content' => array( 'type' => 'string', 'location' => 'xml', ), 'Interval' => array( 'type' => 'integer', 'location' => 'xml', ), 'MaxFrames' => array( 'type' => 'integer', 'location' => 'xml', ), 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'LargeImageDetect' => array( 'type' => 'integer', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Encryption' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Algorithm' => array( 'type' => 'string', 'location' => 'xml', ), - 'Key' => array( 'type' => 'string', 'location' => 'xml', ), - 'IV' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeyId' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeyType' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -4824,18 +3501,6 @@ class Descriptions { 'properties' => array( 'DetectType' => array( 'type' => 'string', 'location' => 'xml', ), 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Async' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Callback' => array( 'type' => 'string', 'location' => 'xml', ), - 'Freeze' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'PornScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AdsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PoliticsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TerrorismScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -4865,8 +3530,6 @@ class Descriptions { 'Label' => array( 'type' => 'string', 'location' => 'xml',), 'Result' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'ForbidState' => array( 'type' => 'integer', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Text' => array( 'type' => 'string', 'location' => 'xml',), 'Object' => array( 'type' => 'string', 'location' => 'xml',), @@ -4880,7 +3543,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4890,7 +3552,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4918,7 +3579,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -4933,18 +3593,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -4956,7 +3604,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -4966,7 +3613,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -4994,7 +3640,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5009,18 +3654,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -5032,7 +3665,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -5042,7 +3674,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5070,7 +3701,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5085,18 +3715,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -5108,7 +3726,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -5118,7 +3735,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5146,7 +3762,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5161,18 +3776,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TeenagerInfo' => array( @@ -5184,7 +3787,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -5194,7 +3796,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5222,7 +3823,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5237,130 +3837,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'QualityInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'integer', 'location' => 'xml',), - 'Msg' => array( 'type' => 'string', 'location' => 'xml',), - 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'OcrResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Width' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Height' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Rotate' => array( 'type' => 'numeric', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'ObjectResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Width' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Height' => array( 'type' => 'numeric', 'location' => 'xml',), - 'Rotate' => array( 'type' => 'numeric', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), ), ), ), @@ -5566,11 +4042,9 @@ class Descriptions { 'CompressionResult' => array('type' => 'integer', 'location' => 'xml',), 'Text' => array('type' => 'string', 'location' => 'xml',), 'Label' => array('type' => 'string', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'Result' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), - 'ForbidState' => array('type' => 'integer', 'location' => 'xml',), 'PornInfo' => array( 'type' => 'object', 'location' => 'xml', @@ -5578,7 +4052,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OcrResults' => array( 'type' => 'array', @@ -5588,7 +4061,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5616,7 +4088,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5631,18 +4102,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -5652,7 +4111,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OcrResults' => array( 'type' => 'array', @@ -5662,7 +4120,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5690,7 +4147,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5705,18 +4161,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -5726,7 +4170,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OcrResults' => array( 'type' => 'array', @@ -5736,7 +4179,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5764,7 +4206,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5779,18 +4220,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -5800,7 +4229,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OcrResults' => array( 'type' => 'array', @@ -5810,7 +4238,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5838,7 +4265,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5853,18 +4279,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TeenagerInfo' => array( @@ -5874,7 +4288,6 @@ class Descriptions { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml', ), 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), 'Label' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), 'SubLabel' => array( 'type' => 'string', 'location' => 'xml', ), 'OcrResults' => array( 'type' => 'array', @@ -5884,7 +4297,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -5912,7 +4324,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -5927,54 +4338,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), ), ), ), @@ -5997,25 +4360,23 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'VoiceSeparate' => array( 'type' => 'object', 'location' => 'xml', @@ -6034,6 +4395,7 @@ class Descriptions { ), ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( @@ -6041,21 +4403,10 @@ class Descriptions { 'Bucket' => array('type' => 'string', 'location' => 'xml', ), 'Object' => array('type' => 'string', 'location' => 'xml', ), 'AuObject' => array('type' => 'string', 'location' => 'xml', ), - 'BassObject' => array( 'type' => 'string', 'location' => 'xml', ), - 'DrumObject' => array( 'type' => 'string', 'location' => 'xml', ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -6165,34 +4516,15 @@ class Descriptions { 'properties' => array( 'Url' => array( 'type' => 'string', 'location' => 'xml', ), 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ), 'Conf' => array( 'location' => 'xml', 'type' => 'object', 'properties' => array( - 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), 'DetectType' => array( 'type' => 'string', 'location' => 'xml', ), 'Callback' => array( 'type' => 'string', 'location' => 'xml', ), 'ReturnHighlightHtml' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallbackType' => array( 'type' => 'integer', 'location' => 'xml', ), ), ), ), @@ -6336,7 +4668,6 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -6346,7 +4677,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -6374,7 +4704,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -6389,18 +4718,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -6409,7 +4726,6 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -6419,7 +4735,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -6447,7 +4762,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -6462,18 +4776,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -6482,7 +4784,6 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -6492,7 +4793,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -6520,7 +4820,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -6535,18 +4834,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -6555,7 +4842,6 @@ class Descriptions { 'properties' => array( 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), - 'Category' => array('type' => 'string', 'location' => 'xml',), 'SubLabel' => array('type' => 'string', 'location' => 'xml',), 'OcrResults' => array( 'type' => 'array', @@ -6565,7 +4851,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Text' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Keywords' => array( 'type' => 'array', 'location' => 'xml', @@ -6593,7 +4878,6 @@ class Descriptions { 'location' => 'xml', 'properties' => array( 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Location' => array( 'type' => 'object', 'location' => 'xml', @@ -6608,18 +4892,6 @@ class Descriptions { ), ), ), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ImageId' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), ), ), ), @@ -6648,23 +4920,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array('type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -6674,23 +4929,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array('type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -6700,23 +4938,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array('type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -6726,23 +4947,6 @@ class Descriptions { 'HitFlag' => array('type' => 'integer', 'location' => 'xml',), 'Score' => array('type' => 'integer', 'location' => 'xml',), 'Keywords' => array('type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), ), @@ -6750,42 +4954,6 @@ class Descriptions { ), ), ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), ), ), ), @@ -6913,7 +5081,6 @@ class Descriptions { ), 'QueueIds' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueIds' ), 'State' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'state' ), - 'Category' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'category' ), 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), ), @@ -6953,7 +5120,6 @@ class Descriptions { 'State' => array( 'type' => 'string', 'location' => 'xml',), 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml',), 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml',), 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), 'NotifyConfig' => array( @@ -6963,10 +5129,6 @@ class Descriptions { 'State' => array( 'type' => 'string', 'location' => 'xml',), 'Type' => array( 'type' => 'string', 'location' => 'xml',), 'Event' => array( 'type' => 'string', 'location' => 'xml',), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml',), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), ), ), ), @@ -6995,21 +5157,18 @@ class Descriptions { 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueID' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), + 'Name' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueID' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'State' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), 'NotifyConfig' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), + 'Url' => array( 'required' => false, 'type' => 'string', 'location' => 'xml', ), + 'Type' => array( 'required' => false, 'type' => 'string', 'location' => 'xml', ), + 'Event' => array( 'required' => false, 'type' => 'string', 'location' => 'xml', ), + 'State' => array( 'required' => false, 'type' => 'string', 'location' => 'xml', ), ), ), ), @@ -7059,56 +5218,34 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'TemplateId' => array( 'location' => 'xml', 'type' => 'string', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -7156,27 +5293,25 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), 'TranscodeTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), 'WatermarkTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'VideoProcess' => array( 'type' => 'object', 'location' => 'xml', @@ -7318,37 +5453,18 @@ class Descriptions { ), ), ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -7396,31 +5512,28 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'VideoMontage' => array( 'type' => 'object', 'location' => 'xml', 'properties' => array( 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - 'Scene' => array( 'type' => 'string', 'location' => 'xml', ), 'Container' => array( 'type' => 'object', 'location' => 'xml', @@ -7438,7 +5551,6 @@ class Descriptions { 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), ), ), 'Audio' => array( @@ -7452,78 +5564,20 @@ class Descriptions { 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), ), ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), ), ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -7571,25 +5625,23 @@ class Descriptions { ), 'parameters' => array( 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), + 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'QueueId' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), + 'CallBack' => array( 'required' => false, 'location' => 'xml', 'type' => 'string', ), 'Input' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), 'Operation' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), 'Animation' => array( 'type' => 'object', 'location' => 'xml', @@ -7626,25 +5678,17 @@ class Descriptions { ), ), 'Output' => array( + 'required' => true, 'type' => 'object', 'location' => 'xml', 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), + 'Region' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), + 'Object' => array( 'required' => true, 'type' => 'string', 'location' => 'xml', ), ), ), ), ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ); } @@ -7678,13490 +5722,4 @@ class Descriptions { ); } - public static function CreateMediaPicProcessJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}pic_jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaPicProcessJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'PicProcess' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsPicInfo' => array( 'type' => 'string', 'location' => 'xml', ), - 'ProcessRule' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaPicProcessJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaSegmentJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSegmentJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Segment' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSegmentJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaVideoTagJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVideoTagJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoTag' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Scenario' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaVideoTagJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaSuperResolutionJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSuperResolutionJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TranscodeTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'WatermarkTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsTsTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'LongShortMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeepTwoTracks' => array( 'type' => 'string', 'location' => 'xml', ), - 'SwitchTrack' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFormat' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - 'Watermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSuperResolutionJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaSDRtoHDRJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSDRtoHDRJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TranscodeTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'WatermarkTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsTsTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'LongShortMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeepTwoTracks' => array( 'type' => 'string', 'location' => 'xml', ), - 'SwitchTrack' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFormat' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - 'Watermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSDRtoHDRJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaDigitalWatermarkJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaDigitalWatermarkJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaDigitalWatermarkJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaExtractDigitalWatermarkJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaExtractDigitalWatermarkJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'ExtractDigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaExtractDigitalWatermarkJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function DetectLiveVideo() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}video/auditing', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DetectLiveVideoOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Conf' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Callback' => array( 'type' => 'string', 'location' => 'xml', ), - 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallbackType' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'StorageConf' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Path' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function DetectLiveVideoOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - - public static function CancelLiveVideoAuditing() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}video/cancel_auditing/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CancelLiveVideoAuditingOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function CancelLiveVideoAuditingOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'DataId' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - - public static function OpticalOcrRecognition() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=OCR', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpticalOcrRecognitionOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - 'Type' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'type' ), - 'LanguageType' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'language-type' ), - 'IsPDF' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'ispdf' ), - 'PdfPageNumber' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pdf-pagenumber' ), - 'IsWord' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'isword' ), - 'EnableWordPolygon' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'enable-word-polygon' ), - ), - ); - } - public static function OpticalOcrRecognitionOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - 'Angel' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'PdfPageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TextDetections' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'DetectedText' => array( 'type' => 'string', 'location' => 'xml', ), - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ItemPolygon' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Polygon' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - 'Words' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Character' => array( 'type' => 'string', 'location' => 'xml', ), - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordCoordPoint' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'WordCoordinate' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - 'WordPolygon' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LeftTop' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'RightTop' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'RightBottom' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'LeftBottom' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function TriggerWorkflow() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}triggerworkflow', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'TriggerWorkflowOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'workflowId' => array( 'required' => true, 'type' => 'string', 'location' => 'query', ), - 'object' => array( 'required' => true, 'type' => 'string', 'location' => 'query', ), - 'name' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - ), - ); - } - public static function TriggerWorkflowOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'InstanceId' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - - public static function GetWorkflowInstances() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}workflowexecution', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetWorkflowInstancesOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'workflowId' => array( 'required' => true, 'type' => 'string', 'location' => 'query', ), - 'name' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'orderByTime' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'size' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'states' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'startCreationTime' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'endCreationTime' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - 'nextToken' => array( 'required' => false, 'type' => 'string', 'location' => 'query', ), - ), - ); - } - public static function GetWorkflowInstancesOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'NextToken' => array( 'type' => 'string', 'location' => 'xml', ), - 'WorkflowExecutionList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'RunId' => array( 'type' => 'string', 'location' => 'xml', ), - 'WorkflowId' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ); - } - - public static function GetWorkflowInstance() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}workflowexecution/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetWorkflowInstanceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function GetWorkflowInstanceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaSnapshotTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSnapshotTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Snapshot' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSnapshotTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Snapshot' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaSnapshotTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaSnapshotTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Snapshot' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaSnapshotTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Snapshot' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaTranscodeTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaTranscodeTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'LongShortMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeepTwoTracks' => array( 'type' => 'string', 'location' => 'xml', ), - 'SwitchTrack' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFormat' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ); - } - public static function CreateMediaTranscodeTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaTranscodeTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaTranscodeTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'LongShortMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeepTwoTracks' => array( 'type' => 'string', 'location' => 'xml', ), - 'SwitchTrack' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFormat' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ); - } - public static function UpdateMediaTranscodeTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaHighSpeedHdTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaHighSpeedHdTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsTsTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaHighSpeedHdTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaHighSpeedHdTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaHighSpeedHdTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsTsTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaHighSpeedHdTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaAnimationTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaAnimationTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateOnlyKeepKeyFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateTimeIntervalOfFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateFramesPerSecond' => array( 'type' => 'string', 'location' => 'xml', ), - 'Quality' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaAnimationTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaAnimationTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaAnimationTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateOnlyKeepKeyFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateTimeIntervalOfFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateFramesPerSecond' => array( 'type' => 'string', 'location' => 'xml', ), - 'Quality' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaAnimationTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaConcatTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaConcatTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'ConcatTemplate' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'DirectConcat' => array( 'type' => 'string', 'location' => 'xml', ), - 'ConcatFragments' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'ConcatFragment', - 'type' => 'object', - 'sentAs' => 'ConcatFragment', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - 'SceneChangeInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Time' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function CreateMediaConcatTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaConcatTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaConcatTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'ConcatTemplate' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'DirectConcat' => array( 'type' => 'string', 'location' => 'xml', ), - 'ConcatFragments' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'ConcatFragment', - 'type' => 'object', - 'sentAs' => 'ConcatFragment', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - 'SceneChangeInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Time' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function UpdateMediaConcatTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaVideoProcessTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVideoProcessTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaVideoProcessTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaVideoProcessTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaVideoProcessTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaVideoProcessTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaVideoMontageTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVideoMontageTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - 'Scene' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ); - } - public static function CreateMediaVideoMontageTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaVideoMontageTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaVideoMontageTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - 'Scene' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ); - } - public static function UpdateMediaVideoMontageTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaVoiceSeparateTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVoiceSeparateTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'AudioMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'AudioConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaVoiceSeparateTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaVoiceSeparateTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaVoiceSeparateTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'AudioMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'AudioConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaVoiceSeparateTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaSuperResolutionTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSuperResolutionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Resolution' => array( 'location' => 'xml', 'type' => 'string', ), - 'EnableScaleUp' => array( 'location' => 'xml', 'type' => 'string', ), - 'Version' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ); - } - public static function CreateMediaSuperResolutionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaSuperResolutionTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaSuperResolutionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Resolution' => array( 'location' => 'xml', 'type' => 'string', ), - 'EnableScaleUp' => array( 'location' => 'xml', 'type' => 'string', ), - 'Version' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ); - } - public static function UpdateMediaSuperResolutionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaPicProcessTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaPicProcessTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'PicProcess' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsPicInfo' => array( 'type' => 'string', 'location' => 'xml', ), - 'ProcessRule' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaPicProcessTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaPicProcessTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaPicProcessTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'PicProcess' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsPicInfo' => array( 'type' => 'string', 'location' => 'xml', ), - 'ProcessRule' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaPicProcessTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaWatermarkTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaWatermarkTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Watermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function CreateMediaWatermarkTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UpdateMediaWatermarkTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaWatermarkTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Watermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function UpdateMediaWatermarkTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function DescribeMediaTemplates() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeMediaTemplatesOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Tag' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'tag' ), - 'Category' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'category' ), - 'Ids' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'ids' ), - 'Name' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'name' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function DescribeMediaTemplatesOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'TotalCount' => array( 'type' => 'string', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - ), - ), - ), - ); - } - - public static function DescribeWorkflow() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}workflow', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeWorkflowOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Ids' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'ids' ), - 'Name' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'name' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function DescribeWorkflowOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'TotalCount' => array( 'type' => 'string', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'MediaWorkflowList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - ), - ), - ), - ); - } - - public static function DeleteWorkflow() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/{Bucket}workflow/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DeleteWorkflowOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function DeleteWorkflowOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'WorkflowId' => array( 'type' => 'string', 'location' => 'xml' ), - ), - ); - } - - public static function CreateInventoryTriggerJob() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}inventorytriggerjob', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateInventoryTriggerJobOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Type' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Manifest' => array( 'type' => 'string', 'location' => 'xml', ), - 'UrlFile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'WorkflowIds' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueType' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallBackFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallBackType' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallBack' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'End' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'AuObject' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpriteObject' => array( 'type' => 'string', 'location' => 'xml', ), - 'StreamExtract' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'JobParam' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TranscodeTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'WatermarkTemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Animation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateOnlyKeepKeyFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateTimeIntervalOfFrame' => array( 'type' => 'string', 'location' => 'xml', ), - 'AnimateFramesPerSecond' => array( 'type' => 'string', 'location' => 'xml', ), - 'Quality' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gop' => array( 'type' => 'string', 'location' => 'xml', ), - 'Preset' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bufsize' => array( 'type' => 'string', 'location' => 'xml', ), - 'Maxrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsTsTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pixfmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'LongShortMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - 'KeepTwoTracks' => array( 'type' => 'string', 'location' => 'xml', ), - 'SwitchTrack' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFormat' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Watermark' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'Watermark', - 'type' => 'object', - 'sentAs' => 'Watermark', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ), - 'RemoveWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Snapshot' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'TimeInterval' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'ConcatTemplate' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Index' => array( 'type' => 'string', 'location' => 'xml', ), - 'DirectConcat' => array( 'type' => 'string', 'location' => 'xml', ), - 'ConcatFragments' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'ConcatFragment', - 'type' => 'object', - 'sentAs' => 'ConcatFragment', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - // 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), 拼接接口不需要Mode参数 - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'VoiceSeparate' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'VideoMontage' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - 'Scene' => array( 'type' => 'string', 'location' => 'xml', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Crf' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AudioMix' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'AudioMixArray' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'type' => 'object', - 'name' => 'AudioMixArray', - 'sentAs' => 'AudioMixArray', - 'properties' => array( - 'AudioSource' => array( 'type' => 'string', 'location' => 'xml', ), - 'MixMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Replace' => array( 'type' => 'string', 'location' => 'xml', ), - 'EffectConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EnableStartFadein' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartFadeinTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableEndFadeout' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndFadeoutTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableBgmFade' => array( 'type' => 'string', 'location' => 'xml', ), - 'BgmFadeTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'VideoProcess' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Enable' => array( 'type' => 'string', 'location' => 'xml', ), - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Segment' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - 'HlsEncrypt' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsHlsEncrypt' => array( 'type' => 'string', 'location' => 'xml', ), - 'UriKey' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'ExtractDigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'VideoTag' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Scenario' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TtsTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleRate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function CreateInventoryTriggerJobOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function DescribeInventoryTriggerJobs() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}inventorytriggerjob', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeInventoryTriggerJobsOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'NextToken' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'nextToken' ), - 'Size' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'size' ), - 'OrderByTime' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'orderByTime' ), - 'States' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'states' ), - 'StartCreationTime' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'startCreationTime' ), - 'EndCreationTime' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'endCreationTime' ), - 'WorkflowId' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'workflowId' ), - 'JobId' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'jobId' ), - 'Name' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'name' ), - ), - ); - } - public static function DescribeInventoryTriggerJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function DescribeInventoryTriggerJob() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}inventorytriggerjob/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeInventoryTriggerJobOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function DescribeInventoryTriggerJobOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CancelInventoryTriggerJob() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}inventorytriggerjob/{/Key*}?cancel', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CancelInventoryTriggerJobOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function CancelInventoryTriggerJobOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaNoiseReductionJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaNoiseReductionJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleRate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaNoiseReductionJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function ImageRepairProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageRepairProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'ci-process' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'query' - ), - 'MaskPic' => array( - 'type' => 'string', - 'location' => 'query', - ), - 'MaskPoly' => array( - 'type' => 'string', - 'location' => 'query', - ), - ), - ); - } - public static function ImageRepairProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function ImageDetectCarProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=DetectCar', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageDetectCarProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function ImageDetectCarProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'CarTags' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Serial' => array( 'type' => 'string', 'location' => 'xml', ), - 'Brand' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Color' => array( 'type' => 'string', 'location' => 'xml', ), - 'Confidence' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Year' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'CarLocation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml', ), - ), - ), - 'PlateContent' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Plate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Color' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'PlateLocation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Y' => array( 'type' => 'numeric', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function ImageAssessQualityProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=AssessQuality', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageAssessQualityProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function ImageAssessQualityProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'LongImage' => array( 'type' => 'string', 'location' => 'xml', ), - 'BlackAndWhite' => array( 'type' => 'string', 'location' => 'xml', ), - 'SmallImage' => array( 'type' => 'string', 'location' => 'xml', ), - 'BigImage' => array( 'type' => 'string', 'location' => 'xml', ), - 'PureImage' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClarityScore' => array( 'type' => 'string', 'location' => 'xml', ), - 'AestheticScore' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - - public static function ImageSearchOpen() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}ImageSearchBucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageSearchOpenOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'MaxCapacity' => array( 'location' => 'xml', 'type' => 'integer', ), - 'MaxQps' => array( 'location' => 'xml', 'type' => 'integer', ), - ), - ); - } - public static function ImageSearchOpenOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function ImageSearchAdd() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}{/Key*}?ci-process=ImageSearch&action=AddImage', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageSearchAddOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'EntityId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CustomContent' => array( 'location' => 'xml', 'type' => 'string', ), - 'Tags' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ); - } - public static function ImageSearchAddOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function ImageSearch() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=ImageSearch&action=SearchImage', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageSearchOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'MatchThreshold' => array( 'type' => 'integer', 'location' => 'query' ), - 'Offset' => array( 'type' => 'integer', 'location' => 'query' ), - 'Limit' => array( 'type' => 'integer', 'location' => 'query' ), - 'Filter' => array( 'type' => 'string', 'location' => 'query' ), - ), - ); - } - public static function ImageSearchOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Count' => array('type' => 'integer', 'location' => 'xml',), - 'ImageInfos' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EntityId' => array( 'type' => 'string', 'location' => 'xml',), - 'CustomContent' => array( 'type' => 'string', 'location' => 'xml',), - 'Tags' => array( 'type' => 'string', 'location' => 'xml',), - 'PicName' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ) - ); - } - - public static function ImageSearchDelete() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}{/Key*}?ci-process=ImageSearch&action=DeleteImage', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageSearchDeleteOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'EntityId' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ); - } - public static function ImageSearchDeleteOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function BindCiService() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'BindCiServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function BindCiServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function GetCiService() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetCiServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetCiServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function UnBindCiService() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}?unbind', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UnBindCiServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function UnBindCiServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function GetHotLink() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?hotlink', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetHotLinkOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetHotLinkOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function AddHotLink() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}?hotlink', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'AddHotLinkOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Hotlink', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Type' => array( 'location' => 'xml', 'type' => 'string', ), - 'Urls' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( 'name' => 'Url', 'type' => 'string', 'location' => 'xml', 'sentAs' => 'Url', ), - ), - ), - ); - } - public static function AddHotLinkOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function OpenOriginProtect() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}?origin-protect', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpenOriginProtectOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function OpenOriginProtectOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function GetOriginProtect() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?origin-protect', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetOriginProtectOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetOriginProtectOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CloseOriginProtect() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/{Bucket}?origin-protect', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CloseOriginProtectOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function CloseOriginProtectOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function ImageDetectFace() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=DetectFace', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageDetectFaceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'MaxFaceNum' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'max-face-num' ), - ), - ); - } - public static function ImageDetectFaceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'ImageWidth' => array('type' => 'integer', 'location' => 'xml',), - 'ImageHeight' => array('type' => 'integer', 'location' => 'xml',), - 'FaceModelVersion' => array('type' => 'string', 'location' => 'xml',), - 'FaceInfos' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml',), - 'Y' => array( 'type' => 'integer', 'location' => 'xml',), - 'Width' => array( 'type' => 'integer', 'location' => 'xml',), - 'Height' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ) - ); - } - - public static function ImageFaceEffect() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=face-effect', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageFaceEffectOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'type' => array( 'type' => 'string', 'location' => 'query', ), - 'whitening' => array( 'type' => 'integer', 'location' => 'query', ), - 'smoothing' => array( 'type' => 'integer', 'location' => 'query', ), - 'faceLifting' => array( 'type' => 'integer', 'location' => 'query', ), - 'eyeEnlarging' => array( 'type' => 'integer', 'location' => 'query', ), - 'gender' => array( 'type' => 'integer', 'location' => 'query', ), - 'age' => array( 'type' => 'integer', 'location' => 'query', ), - 'detectUrl' => array('type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url'), - ), - ); - } - - public static function ImageUrlFaceEffect() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?ci-process=face-effect', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ImageFaceEffectOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'type' => array( 'type' => 'string', 'location' => 'query', ), - 'whitening' => array( 'type' => 'integer', 'location' => 'query', ), - 'smoothing' => array( 'type' => 'integer', 'location' => 'query', ), - 'faceLifting' => array( 'type' => 'integer', 'location' => 'query', ), - 'eyeEnlarging' => array( 'type' => 'integer', 'location' => 'query', ), - 'gender' => array( 'type' => 'integer', 'location' => 'query', ), - 'age' => array( 'type' => 'integer', 'location' => 'query', ), - 'detectUrl' => array('type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url'), - ), - ); - } - public static function ImageFaceEffectOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'ResultImage' => array('type' => 'string', 'location' => 'xml',), - 'ResultMask' => array('type' => 'string', 'location' => 'xml',), - ) - ); - } - - public static function IDCardOCR() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=IDCardOCR', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'IDCardOCROutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'CardSide' => array( 'type' => 'string', 'location' => 'query', ), - 'Config' => array( 'type' => 'string', 'location' => 'query', ), - ), - ); - } - public static function IDCardOCROutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'ResultImage' => array('type' => 'string', 'location' => 'xml',), - 'IdInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Sex' => array( 'type' => 'string', 'location' => 'xml',), - 'Nation' => array( 'type' => 'string', 'location' => 'xml',), - 'Birth' => array( 'type' => 'string', 'location' => 'xml',), - 'Address' => array( 'type' => 'string', 'location' => 'xml',), - 'IdNum' => array( 'type' => 'string', 'location' => 'xml',), - 'Authority' => array( 'type' => 'string', 'location' => 'xml',), - 'ValidDate' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'AdvancedInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IdCard' => array( 'type' => 'string', 'location' => 'xml',), - 'Portrait' => array( 'type' => 'string', 'location' => 'xml',), - 'Quality' => array( 'type' => 'string', 'location' => 'xml',), - 'BorderCodeValue' => array( 'type' => 'string', 'location' => 'xml',), - 'WarnInfos' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ); - } - - public static function IDCardOCRByUpload() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}{/Key*}?ci-process=IDCardOCR', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'IDCardOCRByUploadOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'CardSide' => array( 'type' => 'string', 'location' => 'query', ), - 'Config' => array( 'type' => 'string', 'location' => 'query', ), - 'Body' => array( - 'required' => true, - 'type' => array( 'any' ), - 'location' => 'body' - ), - ), - ); - } - public static function IDCardOCRByUploadOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'ResultImage' => array('type' => 'string', 'location' => 'xml',), - 'IdInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Sex' => array( 'type' => 'string', 'location' => 'xml',), - 'Nation' => array( 'type' => 'string', 'location' => 'xml',), - 'Birth' => array( 'type' => 'string', 'location' => 'xml',), - 'Address' => array( 'type' => 'string', 'location' => 'xml',), - 'IdNum' => array( 'type' => 'string', 'location' => 'xml',), - 'Authority' => array( 'type' => 'string', 'location' => 'xml',), - 'ValidDate' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'AdvancedInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IdCard' => array( 'type' => 'string', 'location' => 'xml',), - 'Portrait' => array( 'type' => 'string', 'location' => 'xml',), - 'Quality' => array( 'type' => 'string', 'location' => 'xml',), - 'BorderCodeValue' => array( 'type' => 'string', 'location' => 'xml',), - 'WarnInfos' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ); - } - - public static function GetLiveCode() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?ci-process=GetLiveCode', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetLiveCodeOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetLiveCodeOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'LiveCode' => array('type' => 'string', 'location' => 'xml',), - ) - ); - } - - public static function GetActionSequence() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?ci-process=GetActionSequence', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetActionSequenceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetActionSequenceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'ActionSequence' => array('type' => 'string', 'location' => 'xml',), - ) - ); - } - - public static function DescribeDocProcessBuckets() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/docbucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeDocProcessBucketsOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Regions' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'regions' ), - 'BucketNames' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketNames' ), - 'BucketName' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketName' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function DescribeDocProcessBucketsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'DocBucketList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - 'AliasBucketId' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ); - } - - public static function UpdateDocProcessQueue() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}docqueue/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateDocProcessQueueOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueID' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateDocProcessQueueOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Queue' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaQualityEstimateJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaQualityEstimateJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'QualityEstimateConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaQualityEstimateJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function CreateMediaStreamExtractJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaStreamExtractJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'StreamExtracts' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'StreamExtract', - 'type' => 'object', - 'sentAs' => 'StreamExtract', - 'properties' => array( - 'Index' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaStreamExtractJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ), - ); - } - - public static function FileJobs4Hash() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=filehash', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'FileJobs4HashOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Type' => array( 'required' => true, 'type' => 'string', 'location' => 'query', 'sentAs' => 'type', ), - 'AddToHeader' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'addtoheader', ), - ), - ); - } - public static function FileJobs4HashOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'FileHashCodeResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MD5' => array( 'type' => 'string', 'location' => 'xml',), - 'SHA1' => array( 'type' => 'string', 'location' => 'xml',), - 'SHA256' => array( 'type' => 'string', 'location' => 'xml',), - 'FileSize' => array( 'type' => 'numeric', 'location' => 'xml',), - ), - ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml',), - 'Object' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ) - ); - } - - public static function OpenFileProcessService() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}file_bucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpenFileProcessServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function OpenFileProcessServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'FileBucket' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ) - ); - } - - public static function GetFileProcessQueueList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}file_queue', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetFileProcessQueueListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'QueueIds' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueIds', ), - 'State' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'state', ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber', ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize', ), - ), - ); - } - public static function GetFileProcessQueueListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'TotalCount' => array( 'type' => 'numeric', 'location' => 'xml',), - 'PageNumber' => array( 'type' => 'numeric', 'location' => 'xml',), - 'PageSize' => array( 'type' => 'numeric', 'location' => 'xml',), - 'QueueList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'State' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml',), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml',), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml',), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml',), - 'State' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'Event' => array( 'type' => 'string', 'location' => 'xml',), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml',), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml',), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml',), - 'MqName' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'NonExistPIDs' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ) - ); - } - - public static function UpdateFileProcessQueue() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}file_queue/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateFileProcessQueueOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateFileProcessQueueOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Queue' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'State' => array( 'type' => 'string', 'location' => 'xml',), - 'Category' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml',), - 'MaxSize' => array( 'type' => 'numeric', 'location' => 'xml',), - 'MaxConcurrent' => array( 'type' => 'numeric', 'location' => 'xml',), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateFileHashCodeJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}file_jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateFileHashCodeJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileHashCodeConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'AddToHeader' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateFileHashCodeJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileHashCodeConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'AddToHeader' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileHashCodeResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MD5' => array( 'type' => 'string', 'location' => 'xml', ), - 'SHA1' => array( 'type' => 'string', 'location' => 'xml', ), - 'SHA256' => array( 'type' => 'string', 'location' => 'xml', ), - 'LastModified' => array( 'type' => 'string', 'location' => 'xml', ), - 'Etag' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileSize' => array( 'type' => 'numeric', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function GetFileHashCodeResult() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}file_jobs/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetFileHashCodeResultOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function GetFileHashCodeResultOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileHashCodeConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'AddToHeader' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileHashCodeResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MD5' => array( 'type' => 'string', 'location' => 'xml', ), - 'SHA1' => array( 'type' => 'string', 'location' => 'xml', ), - 'SHA256' => array( 'type' => 'string', 'location' => 'xml', ), - 'LastModified' => array( 'type' => 'string', 'location' => 'xml', ), - 'Etag' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileSize' => array( 'type' => 'numeric', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - 'NonExistJobIds' => array('type' => 'string', 'location' => 'xml',), - ), - ); - } - - public static function CreateFileUncompressJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}file_jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateFileUncompressJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileUncompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'PrefixReplaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'UnCompressKey' => array( 'type' => 'string', 'location' => 'xml', ), - 'ListingFile' => array( 'type' => 'boolean', 'location' => 'xml', 'format' => 'boolean-string',), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateFileUncompressJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileUncompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'PrefixReplaced' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileUncompressResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileCount' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function GetFileUncompressResult() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}file_jobs/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetFileUncompressResultOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function GetFileUncompressResultOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Progress' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileUncompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'PrefixReplaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'UnCompressKey' => array( 'type' => 'string', 'location' => 'xml', ), - 'ListingFile' => array( 'type' => 'boolean', 'location' => 'xml', ), - ), - ), - 'FileUncompressResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileCount' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileList' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'IsTruncated' => array( 'type' => 'boolean', 'location' => 'xml', ), - 'Contents' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Key' => array( 'type' => 'string', 'location' => 'xml', ), - 'LastModified' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileSize' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - 'NonExistJobIds' => array('type' => 'string', 'location' => 'xml',), - ), - ); - } - - public static function CreateFileCompressJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}file_jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateFileCompressJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'FileCompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Flatten' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'UrlList' => array( 'type' => 'string', 'location' => 'xml', ), - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'Keys' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true), - 'items' => array( - 'name' => 'Key', - 'type' => 'string', - 'sentAs' => 'Key', - 'location' => 'xml', - ) - ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateFileCompressJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileCompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Flatten' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'UrlList' => array( 'type' => 'string', 'location' => 'xml', ), - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'Key' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'FileCompressResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function GetFileCompressResult() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}file_jobs/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetFileCompressResultOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - ); - } - public static function GetFileCompressResultOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FileCompressConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Flatten' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'UrlList' => array( 'type' => 'string', 'location' => 'xml', ), - 'Prefix' => array( 'type' => 'string', 'location' => 'xml', ), - 'Key' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'FileCompressResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - 'NonExistJobIds' => array('type' => 'string', 'location' => 'xml',), - ), - ); - } - - public static function CreateM3U8PlayListJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}m3u8_playlist', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateM3U8PlayListJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'StartTime' => array( 'location' => 'query', 'type' => 'integer', 'sentAs' => 'startTime'), - 'EndTime' => array( 'location' => 'query', 'type' => 'integer', 'sentAs' => 'endTime'), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'M3U8List' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array('xmlFlattened' => true), - 'items' => array( - 'name' => 'M3U8List', - 'type' => 'object', - 'sentAs' => 'M3U8List', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Index' => array( 'type' => 'string', 'location' => 'xml', ), - 'ObjectPath' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function CreateM3U8PlayListJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'M3U8List' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Index' => array( 'type' => 'string', 'location' => 'xml', ), - 'ObjectPath' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'ResultInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'OutputUrl' => array( 'type' => 'string', 'location' => 'xml', ), - 'ErrorInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ObjectPath' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function GetPicQueueList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}picqueue', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetPicQueueListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'QueueIds' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueIds' ), - 'State' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'state' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetPicQueueListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'QueueList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - 'NonExistPIDs' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ); - } - - public static function UpdatePicQueue() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}picqueue/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdatePicQueueOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdatePicQueueOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Queue' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function GetPicBucketList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/picbucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetPicBucketListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Regions' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'regions' ), - 'BucketNames' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketNames' ), - 'BucketName' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketName' ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetPicBucketListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PicBucketList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ); - } - - public static function GetAiBucketList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/ai_bucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetAiBucketListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Regions' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'regions' ), - 'BucketNames' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketNames' ), - 'BucketName' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketName' ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetAiBucketListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AiBucketList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ); - } - - public static function OpenAiService() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}ai_bucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpenAiServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function OpenAiServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'AiBucket' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AliasBucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - - public static function CloseAiService() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/{Bucket}ai_bucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CloseAiServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function CloseAiServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'BucketName' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - - public static function GetAiQueueList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}ai_queue', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetAiQueueListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'QueueIds' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueIds' ), - 'State' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'state' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetAiQueueListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'QueueList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - 'NonExistPIDs' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ); - } - - public static function UpdateAiQueue() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}ai_queue/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateAiQueueOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateAiQueueOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Queue' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaTranscodeProTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaTranscodeProTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Interlaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoFpsAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaTranscodeProTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'TransProTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Interlaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoFpsAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaTranscodeProTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaTranscodeProTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Interlaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoFpsAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaTranscodeProTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'TransProTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Interlaced' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Rotate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TimeInterval' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Start' => array( 'type' => 'string', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Remove' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TransConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AdjDarMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckReso' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResoAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckAudioBitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'AudioBitrateAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsCheckVideoFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoFpsAdjMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteMetadata' => array( 'type' => 'string', 'location' => 'xml', ), - 'IsHdr2Sdr' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceTtsTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceTtsTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - public static function CreateVoiceTtsTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'TtsTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateVoiceTtsTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateVoiceTtsTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - public static function UpdateVoiceTtsTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'TtsTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaSmartCoverTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSmartCoverTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSmartCoverTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaSmartCoverTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaSmartCoverTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaSmartCoverTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'SmartCover' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Count' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeleteDuplicates' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceSpeechRecognitionTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceSpeechRecognitionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateVoiceSpeechRecognitionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateVoiceSpeechRecognitionTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateVoiceSpeechRecognitionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateVoiceSpeechRecognitionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceTtsJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceTtsJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'TtsConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'InputType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TtsTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateVoiceTtsJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateName' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'TtsTpl' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'VoiceType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Volume' => array( 'type' => 'string', 'location' => 'xml', ), - 'Speed' => array( 'type' => 'string', 'location' => 'xml', ), - 'Emotion' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'TtsConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'InputType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MediaInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'NumStream' => array( 'type' => 'integer', 'location' => 'xml', ), - 'NumProgram' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FormatName' => array( 'type' => 'string', 'location' => 'xml', ), - 'FormatLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Size' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Stream' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Video' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'ColorPrimaries' => array( 'type' => 'string', 'location' => 'xml', ), - 'ColorRange' => array( 'type' => 'string', 'location' => 'xml', ), - 'ColorTransfer' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - 'HasBFrame' => array( 'type' => 'integer', 'location' => 'xml', ), - 'RefFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Sar' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dar' => array( 'type' => 'string', 'location' => 'xml', ), - 'PixFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'FieldOrder' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AvgFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'NumFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Audio' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleRate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Channel' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ChannelLayout' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Subtitle' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'MediaResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'OutputFile' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'ObjectName' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - 'Md5Info' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ObjectName' => array( 'type' => 'string', 'location' => 'xml',), - 'Md5' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateAiTranslationJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateAiTranslationJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'Lang' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'BasicType' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'NoNeedOutput' => array( 'type' => 'string', 'location' => 'xml', ), - 'Translation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Lang' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateAiTranslationJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'Lang' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'BasicType' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'Translation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Lang' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'AITranslateResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Result' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceSpeechRecognitionJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceSpeechRecognitionJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateVoiceSpeechRecognitionJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateName' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SpeechRecognition' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'EngineModelType' => array( 'type' => 'string', 'location' => 'xml', ), - 'ChannelNum' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ResTextFormat' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterDirty' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterModal' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ConvertNumMode' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerDiarization' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SpeakerNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FilterPunc' => array( 'type' => 'integer', 'location' => 'xml', ), - 'OutputFileType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashAsr' => array( 'type' => 'string', 'location' => 'xml', ), - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'FirstChannelOnly' => array( 'type' => 'integer', 'location' => 'xml', ), - 'WordInfo' => array( 'type' => 'integer', 'location' => 'xml', ), - 'SentenceMaxLength' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SpeechRecognitionResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'AudioTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Result' => array( 'type' => 'string', 'location' => 'xml', ), - 'FlashResult' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'channel_id' => array( 'type' => 'integer', 'location' => 'xml',), - 'text' => array( 'type' => 'string', 'location' => 'xml',), - 'sentence_list' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'text' => array( 'type' => 'string', 'location' => 'xml',), - 'start_time' => array( 'type' => 'integer', 'location' => 'xml',), - 'end_time' => array( 'type' => 'integer', 'location' => 'xml',), - 'speaker_id' => array( 'type' => 'integer', 'location' => 'xml',), - 'word_list' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'word' => array( 'type' => 'string', 'location' => 'xml',), - 'start_time' => array( 'type' => 'integer', 'location' => 'xml',), - 'end_time' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - 'ResultDetail' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FinalSentence' => array( 'type' => 'string', 'location' => 'xml',), - 'SliceSentence' => array( 'type' => 'string', 'location' => 'xml',), - 'StartMs' => array( 'type' => 'string', 'location' => 'xml',), - 'EndMs' => array( 'type' => 'string', 'location' => 'xml',), - 'WordsNum' => array( 'type' => 'string', 'location' => 'xml',), - 'SpeechSpeed' => array( 'type' => 'string', 'location' => 'xml',), - 'SpeakerId' => array( 'type' => 'string', 'location' => 'xml',), - 'Words' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Word' => array( 'type' => 'string', 'location' => 'xml',), - 'OffsetStartMs' => array( 'type' => 'string', 'location' => 'xml',), - 'OffsetEndMs' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateAiWordsGeneralizeJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateAiWordsGeneralizeJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'WordsGeneralize' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'NerMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegMethod' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateAiWordsGeneralizeJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'WordsGeneralize' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'NerMethod' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegMethod' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'WordsGeneralizeResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'WordsGeneralizeLable' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Category' => array( 'type' => 'string', 'location' => 'xml',), - 'Word' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - 'WordsGeneralizeToken' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Word' => array( 'type' => 'string', 'location' => 'xml',), - 'Offset' => array( 'type' => 'string', 'location' => 'xml',), - 'Length' => array( 'type' => 'string', 'location' => 'xml',), - 'Pos' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaVideoEnhanceJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVideoEnhanceJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'WatermarkTemplateId' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'WatermarkTemplateId', - 'type' => 'string', - 'location' => 'xml', - 'sentAs' => 'WatermarkTemplateId', - ), - ), - 'Watermark' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( - 'name' => 'Watermark', - 'type' => 'object', - 'sentAs' => 'Watermark', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SlideConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SlideMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'XSlideSpeed' => array( 'type' => 'string', 'location' => 'xml', ), - 'YSlideSpeed' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaVideoEnhanceJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Progress' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueType' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateName' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Watermark' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pos' => array( 'type' => 'string', 'location' => 'xml', ), - 'LocMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dx' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dy' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'Image' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Background' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Text' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FontSize' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontType' => array( 'type' => 'string', 'location' => 'xml', ), - 'FontColor' => array( 'type' => 'string', 'location' => 'xml', ), - 'Transparency' => array( 'type' => 'string', 'location' => 'xml', ), - 'Text' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SlideConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SlideMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'XSlideSpeed' => array( 'type' => 'string', 'location' => 'xml', ), - 'YSlideSpeed' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ), - 'WatermarkTemplateId' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MediaInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'NumStream' => array( 'type' => 'integer', 'location' => 'xml', ), - 'NumProgram' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FormatName' => array( 'type' => 'string', 'location' => 'xml', ), - 'FormatLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Size' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Stream' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Video' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - 'HasBFrame' => array( 'type' => 'integer', 'location' => 'xml', ), - 'RefFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Sar' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dar' => array( 'type' => 'string', 'location' => 'xml', ), - 'PixFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'FieldOrder' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AvgFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'NumFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Audio' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleRate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Channel' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ChannelLayout' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Subtitle' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'MediaResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'OutputFile' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'ObjectName' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - 'Md5Info' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ObjectName' => array( 'type' => 'string', 'location' => 'xml',), - 'Md5' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - 'DigitalWatermark' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - 'IgnoreError' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaVideoEnhanceTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaVideoEnhanceTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function CreateMediaVideoEnhanceTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaVideoEnhanceTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaVideoEnhanceTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - public static function UpdateMediaVideoEnhanceTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Transcode' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Container' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'ClipConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Duration' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'Video' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Width' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'string', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Audio' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Codec' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'string', 'location' => 'xml', ), - 'Channels' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'SuperResolution' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Resolution' => array( 'type' => 'string', 'location' => 'xml', ), - 'EnableScaleUp' => array( 'type' => 'string', 'location' => 'xml', ), - 'Version' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'SDRtoHDR' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'HdrMode' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'ColorEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Contrast' => array( 'type' => 'string', 'location' => 'xml', ), - 'Correction' => array( 'type' => 'string', 'location' => 'xml', ), - 'Saturation' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MsSharpen' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SharpenLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'FrameEnhance' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'FrameDoubling' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function OpenImageSlim() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}?image-slim', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpenImageSlimOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'ImageSlim', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'SlimMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'Suffixs' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Suffix' => array( - 'type' => 'array', - 'location' => 'xml', - 'data' => array( - 'xmlFlattened' => true, - ), - 'items' => array( 'name' => 'Suffix', 'type' => 'string', 'location' => 'xml', 'sentAs' => 'Suffix', ), - ), - ), - ), - ), - ); - } - public static function OpenImageSlimOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ) - ); - } - - public static function CloseImageSlim() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/{Bucket}?image-slim', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CloseImageSlimOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function CloseImageSlimOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - ) - ); - } - - public static function GetImageSlim() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?image-slim', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetImageSlimOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function GetImageSlimOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Status' => array( 'type' => 'string', 'location' => 'xml', ), - 'SlimMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'Suffixs' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Suffix' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ) - ); - } - - public static function AutoTranslationBlockProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}?ci-process=AutoTranslationBlock', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'AutoTranslationBlockProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'InputText' => array( 'type' => 'string', 'location' => 'query', ), - 'SourceLang' => array( 'type' => 'string', 'location' => 'query', ), - 'TargetLang' => array( 'type' => 'string', 'location' => 'query', ), - 'TextDomain' => array( 'type' => 'string', 'location' => 'query', ), - 'TextStyle' => array( 'type' => 'string', 'location' => 'query', ), - ), - ); - } - public static function AutoTranslationBlockProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'Body' => array( - 'type' => 'string', - 'instanceOf' => 'GuzzleHttp\\Psr7\\Stream', - 'location' => 'body', - ), - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - ) - ); - } - - public static function RecognizeLogoProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=RecognizeLogo', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'RecognizeLogoProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - ), - ); - } - public static function RecognizeLogoProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Status' => array('type' => 'integer', 'location' => 'xml',), - 'LogoInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Point' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'string', - 'location' => 'xml', - ), - ), - ), - ), - ), - ), - ), - ) - ); - } - - public static function DetectLabelProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=detect-label', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DetectLabelProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - 'Scenes' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'scenes' ), - ), - ); - } - public static function DetectLabelProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Labels' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - 'WebLabels' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Labels' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'CameraLabels' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Labels' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'AlbumLabels' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Labels' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - 'NewsLabels' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Labels' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ) - ); - } - - public static function AIGameRecProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=AIGameRec', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'AIGameRecProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - ), - ); - } - public static function AIGameRecProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'GameLabels' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Confidence' => array( 'type' => 'integer', 'location' => 'xml',), - 'FirstCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'SecondCategory' => array( 'type' => 'string', 'location' => 'xml',), - 'GameName' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ) - ); - } - - public static function AIBodyRecognitionProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=AIBodyRecognition', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'AIBodyRecognitionProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - ), - ); - } - public static function AIBodyRecognitionProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Status' => array('type' => 'integer', 'location' => 'xml',), - 'PedestrianInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Point' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'string', - 'location' => 'xml', - ), - ), - ), - ), - ), - ), - ), - ) - ); - } - - public static function DetectPetProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=detect-pet', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DetectPetProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - ), - ); - } - public static function DetectPetProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Status' => array('type' => 'integer', 'location' => 'xml',), - 'ResultInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml',), - 'Y' => array( 'type' => 'integer', 'location' => 'xml',), - 'Height' => array( 'type' => 'integer', 'location' => 'xml',), - 'Width' => array( 'type' => 'integer', 'location' => 'xml',), - ), - ), - ), - ), - ), - ) - ); - } - - public static function AILicenseRecProcess() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=AILicenseRec', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'AILicenseRecProcessOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'DetectUrl' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'detect-url' ), - 'CardType' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'CardType' ), - ), - ); - } - public static function AILicenseRecProcessOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Status' => array('type' => 'integer', 'location' => 'xml',), - 'IdInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'DetectedText' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Point' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'string', - 'location' => 'xml', - ), - ), - ), - ), - ), - ), - ), - ) - ); - } - - public static function CreateMediaTargetRecTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaTargetRecTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaTargetRecTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaTargetRecTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaTargetRecTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaTargetRecTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaTargetRecJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaTargetRecJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaTargetRecJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateName' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VideoTargetRec' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Body' => array( 'type' => 'string', 'location' => 'xml', ), - 'Pet' => array( 'type' => 'string', 'location' => 'xml', ), - 'Car' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'VideoTargetRecResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BodyRecognition' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Time' => array( 'type' => 'string', 'location' => 'xml',), - 'Url' => array( 'type' => 'string', 'location' => 'xml',), - 'BodyInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - 'PetRecognition' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Time' => array( 'type' => 'string', 'location' => 'xml',), - 'Url' => array( 'type' => 'string', 'location' => 'xml',), - 'PetInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - 'CarRecognition' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Time' => array( 'type' => 'string', 'location' => 'xml',), - 'Url' => array( 'type' => 'string', 'location' => 'xml',), - 'CarInfo' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Score' => array( 'type' => 'integer', 'location' => 'xml',), - 'Location' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'X' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Y' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaSegmentVideoBodyJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaSegmentVideoBodyJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegmentVideoBody' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegmentType' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundRed' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundGreen' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundBlue' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundLogoUrl' => array( 'type' => 'string', 'location' => 'xml', ), - 'BinaryThreshold' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveRed' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveGreen' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveBlue' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaSegmentVideoBodyJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateName' => array( 'type' => 'string', 'location' => 'xml', ), - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegmentVideoBody' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Mode' => array( 'type' => 'string', 'location' => 'xml', ), - 'SegmentType' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundRed' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundGreen' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundBlue' => array( 'type' => 'string', 'location' => 'xml', ), - 'BackgroundLogoUrl' => array( 'type' => 'string', 'location' => 'xml', ), - 'BinaryThreshold' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveRed' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveGreen' => array( 'type' => 'string', 'location' => 'xml', ), - 'RemoveBlue' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Output' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'MediaInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'NumStream' => array( 'type' => 'integer', 'location' => 'xml', ), - 'NumProgram' => array( 'type' => 'integer', 'location' => 'xml', ), - 'FormatName' => array( 'type' => 'string', 'location' => 'xml', ), - 'FormatLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Size' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'Stream' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Video' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Profile' => array( 'type' => 'string', 'location' => 'xml', ), - 'Height' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Width' => array( 'type' => 'integer', 'location' => 'xml', ), - 'HasBFrame' => array( 'type' => 'integer', 'location' => 'xml', ), - 'RefFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Sar' => array( 'type' => 'string', 'location' => 'xml', ), - 'Dar' => array( 'type' => 'string', 'location' => 'xml', ), - 'PixFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'FieldOrder' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Fps' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AvgFps' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'NumFrames' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Audio' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'CodecName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecLongName' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTimeBase' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTagString' => array( 'type' => 'string', 'location' => 'xml', ), - 'CodecTag' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleFmt' => array( 'type' => 'string', 'location' => 'xml', ), - 'SampleRate' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Channel' => array( 'type' => 'integer', 'location' => 'xml', ), - 'ChannelLayout' => array( 'type' => 'string', 'location' => 'xml', ), - 'Timebase' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Duration' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Bitrate' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - 'Subtitle' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Index' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Language' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ), - ), - 'MediaResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'OutputFile' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Bucket' => array( 'type' => 'string', 'location' => 'xml', ), - 'Region' => array( 'type' => 'string', 'location' => 'xml', ), - 'ObjectName' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - 'Md5Info' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ObjectName' => array( 'type' => 'string', 'location' => 'xml',), - 'Md5' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function OpenAsrService() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}asrbucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'OpenAsrServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function OpenAsrServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array('type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type',), - 'ContentLength' => array('type' => 'numeric', 'minimum' => 0, 'location' => 'header', 'sentAs' => 'Content-Length',), - 'AsrBucket' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ) - ); - } - - public static function GetAsrBucketList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/asrbucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetAsrBucketListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Regions' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'regions' ), - 'BucketNames' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketNames' ), - 'BucketName' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'bucketName' ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetAsrBucketListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AsrBucketList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'BucketId' => array( 'type' => 'string', 'location' => 'xml',), - 'Name' => array( 'type' => 'string', 'location' => 'xml',), - 'Region' => array( 'type' => 'string', 'location' => 'xml',), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ); - } - - public static function CloseAsrService() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/{Bucket}asrbucket', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CloseAsrServiceOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - ), - ); - } - public static function CloseAsrServiceOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'BucketName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ); - } - - public static function GetAsrQueueList() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}asrqueue', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetAsrQueueListOutput', - 'responseType' => 'model', - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'QueueIds' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'queueIds' ), - 'State' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'state' ), - 'PageNumber' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageNumber' ), - 'PageSize' => array( 'type' => 'string', 'location' => 'query', 'sentAs' => 'pageSize' ), - ), - ); - } - public static function GetAsrQueueListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'TotalCount' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageNumber' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PageSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'QueueList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - 'NonExistPIDs' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ); - } - - public static function UpdateAsrQueue() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}asrqueue/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateAsrQueueOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateAsrQueueOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Queue' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'MaxSize' => array( 'type' => 'integer', 'location' => 'xml', ), - 'MaxConcurrent' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NotifyConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'Event' => array( 'type' => 'string', 'location' => 'xml', ), - 'ResultFormat' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'Url' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateMediaNoiseReductionTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateMediaNoiseReductionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateMediaNoiseReductionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function UpdateMediaNoiseReductionTemplate() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/{Bucket}template/{/Key*}', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateMediaNoiseReductionTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Key' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'required' => true, 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function UpdateMediaNoiseReductionTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Template' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'Name' => array( 'type' => 'string', 'location' => 'xml', ), - 'TemplateId' => array( 'type' => 'string', 'location' => 'xml', ), - 'BucketId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Category' => array( 'type' => 'string', 'location' => 'xml', ), - 'UpdateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreateTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'NoiseReduction' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Format' => array( 'type' => 'string', 'location' => 'xml', ), - 'Samplerate' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceSoundHoundJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceSoundHoundJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateVoiceSoundHoundJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'SoundHoundResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SongList' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Inlier' => array( 'type' => 'integer', 'location' => 'xml',), - 'SingerName' => array( 'type' => 'string', 'location' => 'xml',), - 'SongName' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - ); - } - - public static function CreateVoiceVocalScoreJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateVoiceVocalScoreJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( 'required' => true, 'type' => 'string', 'location' => 'uri', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VocalScore' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'StandardObject' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackMqConfig' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'MqRegion' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqMode' => array( 'type' => 'string', 'location' => 'xml', ), - 'MqName' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - ), - ); - } - public static function CreateVoiceVocalScoreJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'x-ci-request-id', ), - 'ContentType' => array( 'type' => 'string', 'location' => 'header', 'sentAs' => 'Content-Type', ), - 'ContentLength' => array( 'type' => 'numeric', 'minimum'=> 0, 'location' => 'header', 'sentAs' => 'Content-Length', ), - 'JobsDetail' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Code' => array( 'type' => 'string', 'location' => 'xml', ), - 'Message' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Tag' => array( 'type' => 'string', 'location' => 'xml', ), - 'State' => array( 'type' => 'string', 'location' => 'xml', ), - 'CreationTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'StartTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'string', 'location' => 'xml', ), - 'QueueId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Input' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'Object' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'Operation' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'UserData' => array( 'type' => 'string', 'location' => 'xml', ), - 'JobLevel' => array( 'type' => 'string', 'location' => 'xml', ), - 'VocalScore' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'StandardObject' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), - 'VocalScoreResult' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'PitchScore' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SentenceScores' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'TotalScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'RhythemScore' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'SentenceScores' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'StartTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'EndTime' => array( 'type' => 'numeric', 'location' => 'xml', ), - 'Score' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - 'TotalScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), - ), - ), - - ), - ), - ), - ), - ), - ); - } -// 创建数据集 -// 本接口用于创建一个数据集(Dataset),数据集是由文件元数据构成的集合,用于存储和管理元数据。 -// https://cloud.tencent.com/document/product/460/106020 - public static function CreateDataset() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/dataset', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateDatasetOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Version' => array( 'location' => 'json', 'type' => 'string', ), - 'Volume' => array( 'location' => 'json', 'type' => 'integer', ), - 'TrainingMode' => array( 'location' => 'json', 'type' => 'integer', ), - 'TrainingDataset' => array( 'location' => 'json', 'type' => 'string', ), - 'TrainingURI' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function CreateDatasetOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Dataset' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'BindCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'FileCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'TotalFileSize' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 绑定存储桶与数据集 -// 本文档介绍创建数据集(Dataset)和对象存储(COS)Bucket 的绑定关系,绑定后将使用创建数据集时所指定算子对文件进行处理。 -// 绑定关系创建后,将对 COS 中新增的文件进行准实时的增量追踪扫描,使用创建数据集时所指定算子对文件进行处理,抽取文件元数据信息进行索引。通过此方式为文件建立索引后,您可以使用元数据查询API对元数据进行查询、管理和统计。 - -// https://cloud.tencent.com/document/product/460/106159 - public static function CreateDatasetBinding() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/datasetbinding', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateDatasetBindingOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function CreateDatasetBindingOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Binding' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'State' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Detail' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 创建元数据索引 -// 提取一个 COS 文件的元数据,在数据集中建立索引。会根据数据集中的算子提取不同的元数据建立索引,也支持建立自定义的元数据索引。 -// https://cloud.tencent.com/document/product/460/106022 - public static function CreateFileMetaIndex() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/filemeta', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateFileMetaIndexOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Callback' => array( 'location' => 'json', 'type' => 'string', ), - 'File' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'CustomId' => array( 'location' => 'json', 'type' => 'string', ), - 'Key' => array( 'location' => 'json', 'type' => 'string', ), - 'Value' => array( 'location' => 'json', 'type' => 'string', ), - 'MediaType' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentType' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'MaxFaceNum' => array( 'location' => 'json', 'type' => 'integer', ), - 'Persons' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'PersonId' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - ), - ), - ), - - ); - } - public static function CreateFileMetaIndexOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'EventId' => array( 'location' => 'json', 'type' => 'string', ), - - ), - ); - } - -// 人脸搜索 -// 从数据集中搜索与指定图片最相似的前N张图片并返回人脸坐标可对数据集内文件进行一个或多个人员的人脸识别。 -// https://cloud.tencent.com/document/product/460/106166 - public static function DatasetFaceSearch() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/datasetquery/facesearch', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DatasetFaceSearchOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'MaxFaceNum' => array( 'location' => 'json', 'type' => 'integer', ), - 'Limit' => array( 'location' => 'json', 'type' => 'integer', ), - 'MatchThreshold' => array( 'location' => 'json', 'type' => 'integer', ), - ), - - ); - } - public static function DatasetFaceSearchOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'FaceResult' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'FaceInfos' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'PersonId' => array( 'location' => 'json', 'type' => 'string', ), - 'FaceBoundary' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Height' => array( 'location' => 'json', 'type' => 'integer', ), - 'Width' => array( 'location' => 'json', 'type' => 'integer', ), - 'Left' => array( 'location' => 'json', 'type' => 'integer', ), - 'Top' => array( 'location' => 'json', 'type' => 'integer', ), - ), - ), - 'FaceId' => array( 'location' => 'json', 'type' => 'string', ), - 'Score' => array( 'location' => 'json', 'type' => 'integer', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - ) - ), - ), - - ), - ); - } - -// 简单查询 -// 可以根据已提取的文件元数据(包含文件名、标签、路径、自定义标签、文本等字段)查询和统计数据集内文件,支持逻辑关系表达方式。 -// https://cloud.tencent.com/document/product/460/106375 - public static function DatasetSimpleQuery() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/datasetquery/simple', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DatasetSimpleQueryOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Query' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Operation' => array( 'location' => 'json', 'type' => 'string', ), - 'SubQueries' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Value' => array( 'location' => 'json', 'type' => 'string', ), - 'Operation' => array( 'location' => 'json', 'type' => 'string', ), - 'Field' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - 'Field' => array( 'location' => 'json', 'type' => 'string', ), - 'Value' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - 'MaxResults' => array( 'location' => 'json', 'type' => 'integer', ), - 'NextToken' => array( 'location' => 'json', 'type' => 'string', ), - 'Sort' => array( 'location' => 'json', 'type' => 'string', ), - 'Order' => array( 'location' => 'json', 'type' => 'string', ), - 'Aggregations' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Operation' => array( 'location' => 'json', 'type' => 'string', ), - 'Field' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - 'WithFields' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function DatasetSimpleQueryOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Files' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'ObjectId' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'Filename' => array( 'location' => 'json', 'type' => 'string', ), - 'MediaType' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentType' => array( 'location' => 'json', 'type' => 'string', ), - 'COSStorageClass' => array( 'location' => 'json', 'type' => 'string', ), - 'COSCRC64' => array( 'location' => 'json', 'type' => 'string', ), - 'Size' => array( 'location' => 'json', 'type' => 'integer', ), - 'CacheControl' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentDisposition' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentEncoding' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentLanguage' => array( 'location' => 'json', 'type' => 'string', ), - 'ServerSideEncryption' => array( 'location' => 'json', 'type' => 'string', ), - 'ETag' => array( 'location' => 'json', 'type' => 'string', ), - 'FileModifiedTime' => array( 'location' => 'json', 'type' => 'string', ), - 'CustomId' => array( 'location' => 'json', 'type' => 'string', ), - 'ObjectACL' => array( 'location' => 'json', 'type' => 'string', ), - 'COSTaggingCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - 'Aggregations' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Operation' => array( 'location' => 'json', 'type' => 'string', ), - 'Value' => array( 'location' => 'json', 'type' => 'float', ), - 'Groups' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'Count' => array( 'location' => 'json', 'type' => 'integer', ), - 'Value' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - 'Field' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - 'NextToken' => array( 'location' => 'json', 'type' => 'string', ), - - ), - ); - } - -// 删除数据集 -// 删除一个数据集(Dataset)。 -// https://cloud.tencent.com/document/product/460/106157 - public static function DeleteDataset() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/dataset', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DeleteDatasetOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function DeleteDatasetOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Dataset' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'BindCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'FileCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'TotalFileSize' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 解绑存储桶与数据集 -// 解绑数据集和对象存储(COS)Bucket ,解绑会导致 COS Bucket新增的变更不会同步到数据集,请谨慎操作。 -// https://cloud.tencent.com/document/product/460/106160 - public static function DeleteDatasetBinding() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/datasetbinding', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DeleteDatasetBindingOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function DeleteDatasetBindingOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - - ), - ); - } - -// 删除元数据索引 -// 从数据集内删除一个文件的元信息。无论该文件的元信息是否在数据集内存在,均会返回删除成功。 -// - -// https://cloud.tencent.com/document/product/460/106163 - public static function DeleteFileMetaIndex() { - return array( - 'httpMethod' => 'DELETE', - 'uri' => '/filemeta', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DeleteFileMetaIndexOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function DeleteFileMetaIndexOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - - ), - ); - } - -// 查询数据集 -// 查询一个数据集(Dataset)信息。 -// https://cloud.tencent.com/document/product/460/106155 - public static function DescribeDataset() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/dataset', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeDatasetOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'datasetname' => array( - 'type' => 'string', - 'location' => 'query' - ), - 'statistics' => array( - 'type' => 'string', - 'location' => 'query' - ), - ), - - ); - } - public static function DescribeDatasetOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Dataset' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'BindCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'FileCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'TotalFileSize' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 查询数据集与存储桶的绑定关系 -// 查询数据集和对象存储(COS)Bucket 绑定关系列表。 -// https://cloud.tencent.com/document/product/460/106485 - public static function DescribeDatasetBinding() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/datasetbinding', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeDatasetBindingOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'datasetname' => array( - 'type' => 'string', - 'location' => 'query' - ), - 'uri' => array( - 'type' => 'string', - 'location' => 'query' - ), - ), - - ); - } - public static function DescribeDatasetBindingOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Binding' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'State' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Detail' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 查询绑定关系列表 -// 查询数据集和对象存储(COS)Bucket 绑定关系列表。 -// https://cloud.tencent.com/document/product/460/106161 - public static function DescribeDatasetBindings() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/datasetbindings', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeDatasetBindingsOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'datasetname' => array( - 'type' => 'string', - 'location' => 'query' - ), - 'maxresults' => array( - 'type' => 'integer', - 'location' => 'query' - ), - 'nexttoken' => array( - 'type' => 'string', - 'location' => 'query' - ), - ), - - ); - } - public static function DescribeDatasetBindingsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'NextToken' => array( 'location' => 'json', 'type' => 'string', ), - 'Bindings' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'State' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Detail' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - - ), - ); - } - -// 列出数据集 -// 获取数据集(Dataset)列表。 -// https://cloud.tencent.com/document/product/460/106158 - public static function DescribeDatasets() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/datasets', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeDatasetsOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'maxresults' => array( - 'type' => 'integer', - 'location' => 'query' - ), - 'nexttoken' => array( - 'type' => 'string', - 'location' => 'query' - ), - 'prefix' => array( - 'type' => 'string', - 'location' => 'query' - ), - ), - - ); - } - public static function DescribeDatasetsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Datasets' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'BindCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'FileCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'TotalFileSize' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - 'NextToken' => array( 'location' => 'json', 'type' => 'string', ), - - ), - ); - } - -// 查询元数据索引 -// 获取数据集内已完成索引的一个文件的元数据。 -// https://cloud.tencent.com/document/product/460/106164 - public static function DescribeFileMetaIndex() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/filemeta', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'DescribeFileMetaIndexOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'datasetname' => array( - 'type' => 'string', - 'location' => 'query' - ), - 'uri' => array( - 'type' => 'string', - 'location' => 'query' - ), - ), - - ); - } - public static function DescribeFileMetaIndexOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Files' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'Filename' => array( 'location' => 'json', 'type' => 'string', ), - 'MediaType' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentType' => array( 'location' => 'json', 'type' => 'string', ), - 'COSStorageClass' => array( 'location' => 'json', 'type' => 'string', ), - 'COSCRC64' => array( 'location' => 'json', 'type' => 'string', ), - 'ObjectACL' => array( 'location' => 'json', 'type' => 'string', ), - 'Size' => array( 'location' => 'json', 'type' => 'integer', ), - 'CacheControl' => array( 'location' => 'json', 'type' => 'string', ), - 'ETag' => array( 'location' => 'json', 'type' => 'string', ), - 'FileModifiedTime' => array( 'location' => 'json', 'type' => 'string', ), - ' CustomId' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - - ), - ); - } - -// 图像检索 -// 可通过输入自然语言或图片,基于语义对数据集内文件进行图像检索。 -// https://cloud.tencent.com/document/product/460/106376 - public static function SearchImage() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/datasetquery/imagesearch', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'SearchImageOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Mode' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'Limit' => array( 'location' => 'json', 'type' => 'integer', ), - 'Text' => array( 'location' => 'json', 'type' => 'string', ), - 'MatchThreshold' => array( 'location' => 'json', 'type' => 'integer', ), - ), - - ); - } - public static function SearchImageOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'ImageResult' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'Score' => array( 'location' => 'json', 'type' => 'integer', ), - ) - ), - ), - - ), - ); - } - -// 更新数据集 -// 更新一个数据集(Dataset)信息。 -// https://cloud.tencent.com/document/product/460/106156 - public static function UpdateDataset() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/dataset', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateDatasetOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - ), - - ); - } - public static function UpdateDatasetOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Dataset' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'json', 'type' => 'string', ), - 'Description' => array( 'location' => 'json', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'json', 'type' => 'string', ), - 'BindCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'FileCount' => array( 'location' => 'json', 'type' => 'integer', ), - 'TotalFileSize' => array( 'location' => 'json', 'type' => 'integer', ), - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 更新元数据索引 -// 更新数据集内已索引的一个文件的部分元数据。 -// -//并非所有的元数据都允许您自定义更新,在您发起更新请求时需要填写数据集,默认会根据该数据集的算子进行元数据重新提取并更新已存在的索引,此外您也可以更新部分自定义的元数据索引,如CustomTags、CustomId等字段,具体请参考请求参数一节。 -// https://cloud.tencent.com/document/product/460/106162 - public static function UpdateFileMetaIndex() { - return array( - 'httpMethod' => 'PUT', - 'uri' => '/filemeta', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'UpdateFileMetaIndexOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'DatasetName' => array( 'location' => 'json', 'type' => 'string', ), - 'Callback' => array( 'location' => 'json', 'type' => 'string', ), - 'File' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'CustomId' => array( 'location' => 'json', 'type' => 'string', ), - 'Key' => array( 'location' => 'json', 'type' => 'string', ), - 'Value' => array( 'location' => 'json', 'type' => 'string', ), - 'MediaType' => array( 'location' => 'json', 'type' => 'string', ), - 'ContentType' => array( 'location' => 'json', 'type' => 'string', ), - 'URI' => array( 'location' => 'json', 'type' => 'string', ), - 'MaxFaceNum' => array( 'location' => 'json', 'type' => 'integer', ), - 'Persons' => array( - 'location' => 'json', - 'type' => 'array', - 'items' => array( - 'location' => 'json', - 'type' => 'object', - 'properties' => array( - 'PersonId' => array( 'location' => 'json', 'type' => 'string', ), - ) - ), - ), - ), - ), - ), - - ); - } - public static function UpdateFileMetaIndexOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'EventId' => array( 'location' => 'json', 'type' => 'string', ), - - ), - ); - } -// 压缩包预览 -// 该接口可以在不解压文件的情况下预览压缩包内的内容,包含文件数量、名称、文件时间等,接口为同步请求方式 -// https://cloud.tencent.com/document/product/460/93030 - public static function ZipFilePreview() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}{/Key*}?ci-process=zippreview', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'ZipFilePreviewOutput', - 'responseType' => 'model', - - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Key' => array( - 'type' => 'string', - 'location' => 'uri', - ), - 'zipfileUrl' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'zipfile-url' - ), - 'uncompressKey' => array( - 'type' => 'string', - 'location' => 'query', - 'sentAs' => 'uncompress-key' - ), - ), - - ); - } - public static function ZipFilePreviewOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-cos-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'FileNumber' => array( 'location' => 'xml', 'type' => 'integer', ), - 'IsTruncated' => array( 'location' => 'xml', 'type' => 'string', ), - 'Contents' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Key' => array( 'location' => 'xml', 'type' => 'string', ), - 'LastModified' => array( 'location' => 'xml', 'type' => 'string', ), - 'UncompressedSize' => array( 'location' => 'xml', 'type' => 'integer', ), - ) - ), - ), - - ), - ); - } - -// 获取hls播放密钥 -// 该接口用于获取hls播放密钥。 -// https://cloud.tencent.com/document/product/436/104292 - public static function GetHLSPlayKey() { - return array( - 'httpMethod' => 'GET', - 'uri' => '/{Bucket}playKey', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GetHLSPlayKeyOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - ), - - ); - } - public static function GetHLSPlayKeyOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'PlayKeyList' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'MasterPlayKey' => array( 'location' => 'xml', 'type' => 'string', ), - 'BackupPlayKey' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - - ), - ); - } - -// 提交任务 -// 提交一个视频明水印任务 -// https://cloud.tencent.com/document/product/460/84781 - public static function PostWatermarkJobs() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'PostWatermarkJobsOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Operation' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'WatermarkTemplateId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Output' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bucket' => array( 'location' => 'xml', 'type' => 'string', ), - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'UserData' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobLevel' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - ), - - ); - } - public static function PostWatermarkJobsOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Code' => array( 'location' => 'xml', 'type' => 'string', ), - 'Message' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'CreationTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'EndTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bucket' => array( 'location' => 'xml', 'type' => 'string', ), - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Operation' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'WatermarkTemplateId' => array( 'location' => 'xml', 'type' => 'string', ), - 'UserData' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobLevel' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ) - ), - ), - - ), - ); - } - -// 生成播放列表 -// 生成边转边播的播放列表能够分析视频文件产出 m3u8 文件。生成播放列表后即时播放,并根据播放进度实施按需转码,相比离线转码能极大减少了转码等待时间并大幅度降低了转码和存储开销 -// https://cloud.tencent.com/document/product/460/106683 - public static function GeneratePlayList() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}jobs', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'GeneratePlayListOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Operation' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Transcode' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Container' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Format' => array( 'location' => 'xml', 'type' => 'string', ), - 'ClipConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - 'Video' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Codec' => array( 'location' => 'xml', 'type' => 'string', ), - 'Width' => array( 'location' => 'xml', 'type' => 'string', ), - 'Height' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bitrate' => array( 'location' => 'xml', 'type' => 'string', ), - 'Fps' => array( 'location' => 'xml', 'type' => 'string', ), - 'Gop' => array( 'location' => 'xml', 'type' => 'string', ), - 'Maxrate' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'TransConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'InitialClipNum' => array( 'location' => 'xml', 'type' => 'string', ), - 'CosTag' => array( 'location' => 'xml', 'type' => 'string', ), - 'HlsEncrypt' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'IsHlsEncrypt' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - ), - ), - 'Output' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bucket' => array( 'location' => 'xml', 'type' => 'string', ), - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'UserData' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobLevel' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'CallBack' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackType' => array( 'location' => 'xml', 'type' => 'string', ), - 'CallBackMqConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'MqRegion' => array( 'location' => 'xml', 'type' => 'string', ), - 'MqMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'MqName' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - - ); - } - public static function GeneratePlayListOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'JobsDetail' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Code' => array( 'location' => 'xml', 'type' => 'string', ), - 'Message' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobId' => array( 'location' => 'xml', 'type' => 'string', ), - 'State' => array( 'location' => 'xml', 'type' => 'string', ), - 'Progress' => array( 'location' => 'xml', 'type' => 'string', ), - 'CreationTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'EndTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'QueueId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Input' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'BucketId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Operation' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Transcode' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Container' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Format' => array( 'location' => 'xml', 'type' => 'string', ), - 'ClipConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - 'Video' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Codec' => array( 'location' => 'xml', 'type' => 'string', ), - 'Width' => array( 'location' => 'xml', 'type' => 'string', ), - 'Height' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bitrate' => array( 'location' => 'xml', 'type' => 'string', ), - 'Fps' => array( 'location' => 'xml', 'type' => 'string', ), - 'Gop' => array( 'location' => 'xml', 'type' => 'string', ), - 'Maxrate' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'TransConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'InitialClipNum' => array( 'location' => 'xml', 'type' => 'string', ), - 'CosTag' => array( 'location' => 'xml', 'type' => 'string', ), - 'HlsEncrypt' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'IsHlsEncrypt' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - ), - ), - 'Output' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bucket' => array( 'location' => 'xml', 'type' => 'string', ), - 'Object' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'UserData' => array( 'location' => 'xml', 'type' => 'string', ), - 'JobLevel' => array( 'location' => 'xml', 'type' => 'string', ), - 'TemplateName' => array( 'location' => 'xml', 'type' => 'string', ), - 'MediaInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Format' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'NumStream' => array( 'location' => 'xml', 'type' => 'string', ), - 'NumProgram' => array( 'location' => 'xml', 'type' => 'string', ), - 'FormatName' => array( 'location' => 'xml', 'type' => 'string', ), - 'FormatLongName' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bitrate' => array( 'location' => 'xml', 'type' => 'string', ), - 'Size' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Stream' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Video' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Index' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecName' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecLongName' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTimeBase' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTagString' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTag' => array( 'location' => 'xml', 'type' => 'string', ), - 'ColorPrimaries' => array( 'location' => 'xml', 'type' => 'string', ), - 'ColorRange' => array( 'location' => 'xml', 'type' => 'string', ), - 'ColorTransfer' => array( 'location' => 'xml', 'type' => 'string', ), - 'Profile' => array( 'location' => 'xml', 'type' => 'string', ), - 'Height' => array( 'location' => 'xml', 'type' => 'string', ), - 'Width' => array( 'location' => 'xml', 'type' => 'string', ), - 'HasBFrame' => array( 'location' => 'xml', 'type' => 'string', ), - 'RefFrames' => array( 'location' => 'xml', 'type' => 'string', ), - 'Sar' => array( 'location' => 'xml', 'type' => 'string', ), - 'Dar' => array( 'location' => 'xml', 'type' => 'string', ), - 'PixFormat' => array( 'location' => 'xml', 'type' => 'string', ), - 'FieldOrder' => array( 'location' => 'xml', 'type' => 'string', ), - 'Level' => array( 'location' => 'xml', 'type' => 'string', ), - 'Fps' => array( 'location' => 'xml', 'type' => 'string', ), - 'AvgFps' => array( 'location' => 'xml', 'type' => 'string', ), - 'Timebase' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bitrate' => array( 'location' => 'xml', 'type' => 'string', ), - 'NumFrames' => array( 'location' => 'xml', 'type' => 'string', ), - 'Language' => array( 'location' => 'xml', 'type' => 'string', ), - ) - ), - ), - 'Audio' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Index' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecName' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecLongName' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTimeBase' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTagString' => array( 'location' => 'xml', 'type' => 'string', ), - 'CodecTag' => array( 'location' => 'xml', 'type' => 'string', ), - 'SampleFmt' => array( 'location' => 'xml', 'type' => 'string', ), - 'SampleRate' => array( 'location' => 'xml', 'type' => 'string', ), - 'Channel' => array( 'location' => 'xml', 'type' => 'string', ), - 'ChannelLayout' => array( 'location' => 'xml', 'type' => 'string', ), - 'Timebase' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'Duration' => array( 'location' => 'xml', 'type' => 'string', ), - 'Bitrate' => array( 'location' => 'xml', 'type' => 'string', ), - 'Language' => array( 'location' => 'xml', 'type' => 'string', ), - ) - ), - ), - 'Subtitle' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Index' => array( 'location' => 'xml', 'type' => 'string', ), - 'Language' => array( 'location' => 'xml', 'type' => 'string', ), - ) - ), - ), - ), - ), - ), - ), - 'MediaResult' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'OutputFile' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Bucket' => array( 'location' => 'xml', 'type' => 'string', ), - 'Region' => array( 'location' => 'xml', 'type' => 'string', ), - 'ObjectName' => array( 'location' => 'xml', 'type' => 'string', ), - 'Md5Info' => array( - 'location' => 'xml', - 'type' => 'array', - 'items' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'ObjectName' => array( 'location' => 'xml', 'type' => 'string', ), - 'Md5' => array( 'location' => 'xml', 'type' => 'string', ), - ) - ), - ), - ), - ), - ), - ), - ), - ), - ), - ), - - ), - ); - } - -// 创建模板 -// 创建明水印模板 -// https://cloud.tencent.com/document/product/460/84725 - public static function CreateWatermarkTemplate() { - return array( - 'httpMethod' => 'POST', - 'uri' => '/{Bucket}template', - 'class' => 'Qcloud\\Cos\\Command', - 'responseClass' => 'CreateWatermarkTemplateOutput', - 'responseType' => 'model', - 'data' => array( - 'xmlRoot' => array( - 'name' => 'Request', - ), - ), - 'parameters' => array( - 'Bucket' => array( - 'required' => true, - 'type' => 'string', - 'location' => 'uri', - ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'Watermark' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Type' => array( 'location' => 'xml', 'type' => 'string', ), - 'Pos' => array( 'location' => 'xml', 'type' => 'string', ), - 'LocMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'Dx' => array( 'location' => 'xml', 'type' => 'string', ), - 'Dy' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'EndTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'SlideConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'SlideMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'XSlideSpeed' => array( 'location' => 'xml', 'type' => 'string', ), - 'YSlideSpeed' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Image' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Url' => array( 'location' => 'xml', 'type' => 'string', ), - 'Mode' => array( 'location' => 'xml', 'type' => 'string', ), - 'Width' => array( 'location' => 'xml', 'type' => 'string', ), - 'Height' => array( 'location' => 'xml', 'type' => 'string', ), - 'Transparency' => array( 'location' => 'xml', 'type' => 'string', ), - 'Background' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Text' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'FontSize' => array( 'location' => 'xml', 'type' => 'string', ), - 'FontType' => array( 'location' => 'xml', 'type' => 'string', ), - 'FontColor' => array( 'location' => 'xml', 'type' => 'string', ), - 'Transparency' => array( 'location' => 'xml', 'type' => 'string', ), - 'Text' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - ), - - ); - } - public static function CreateWatermarkTemplateOutput() { - return array( - 'type' => 'object', - 'additionalProperties' => true, - 'properties' => array( - 'RequestId' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'x-ci-request-id', - ), - 'ContentType' => array( - 'type' => 'string', - 'location' => 'header', - 'sentAs' => 'Content-Type', - ), - 'ContentLength' => array( - 'type' => 'numeric', - 'minimum'=> 0, - 'location' => 'header', - 'sentAs' => 'Content-Length', - ), - 'Template' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TemplateId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Name' => array( 'location' => 'xml', 'type' => 'string', ), - 'BucketId' => array( 'location' => 'xml', 'type' => 'string', ), - 'Category' => array( 'location' => 'xml', 'type' => 'string', ), - 'Tag' => array( 'location' => 'xml', 'type' => 'string', ), - 'UpdateTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'CreateTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'Watermark' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Type' => array( 'location' => 'xml', 'type' => 'string', ), - 'Pos' => array( 'location' => 'xml', 'type' => 'string', ), - 'LocMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'Dx' => array( 'location' => 'xml', 'type' => 'string', ), - 'Dy' => array( 'location' => 'xml', 'type' => 'string', ), - 'StartTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'EndTime' => array( 'location' => 'xml', 'type' => 'string', ), - 'SlideConfig' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'SlideMode' => array( 'location' => 'xml', 'type' => 'string', ), - 'XSlideSpeed' => array( 'location' => 'xml', 'type' => 'string', ), - 'YSlideSpeed' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Image' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'Url' => array( 'location' => 'xml', 'type' => 'string', ), - 'Mode' => array( 'location' => 'xml', 'type' => 'string', ), - 'Width' => array( 'location' => 'xml', 'type' => 'string', ), - 'Height' => array( 'location' => 'xml', 'type' => 'string', ), - 'Transparency' => array( 'location' => 'xml', 'type' => 'string', ), - 'Background' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - 'Text' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'FontSize' => array( 'location' => 'xml', 'type' => 'string', ), - 'FontType' => array( 'location' => 'xml', 'type' => 'string', ), - 'FontColor' => array( 'location' => 'xml', 'type' => 'string', ), - 'Transparency' => array( 'location' => 'xml', 'type' => 'string', ), - 'Text' => array( 'location' => 'xml', 'type' => 'string', ), - ), - ), - ), - ), - ), - ), - - ), - ); - } - - - } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ExceptionMiddleware.php b/src/vendor/qcloud/cos-sdk-v5/src/ExceptionMiddleware.php index f2066b858..3bc980af1 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ExceptionMiddleware.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ExceptionMiddleware.php @@ -6,6 +6,7 @@ use Qcloud\Cos\Exception\ServiceResponseException; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use GuzzleHttp\Exception\RequestException; class ExceptionMiddleware { private $nextHandler; @@ -42,6 +43,7 @@ class ExceptionMiddleware { return $response; } + //throw RequestException::create($request, $response); $parts = $this->parser->parse($request, $response); $className = 'Qcloud\\Cos\\Exception\\' . $parts['code']; diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ExceptionParser.php b/src/vendor/qcloud/cos-sdk-v5/src/ExceptionParser.php index 8b48c3edc..c15400bb2 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ExceptionParser.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ExceptionParser.php @@ -28,7 +28,7 @@ class ExceptionParser { } try { - $xml = new \SimpleXMLElement(mb_convert_encoding($body, 'UTF-8')); + $xml = new \SimpleXMLElement(utf8_encode($body)); $this->parseBody($xml, $data); return $data; } catch (\Exception $e) { @@ -41,9 +41,9 @@ class ExceptionParser { /** * Parses additional exception information from the response headers * - * @param RequestInterface $request Request that was issued - * @param ResponseInterface $response The response from the request - * @param array $data The current set of exception data + * @param RequestInterface $request Request that was issued + * @param Response $response The response from the request + * @param array $data The current set of exception data */ protected function parseHeaders(RequestInterface $request, ResponseInterface $response, array &$data) { $data['message'] = $response->getStatusCode() . ' ' . $response->getReasonPhrase(); diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/BlindWatermarkTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/BlindWatermarkTemplate.php index b7f5ca71b..0f03b1ea2 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/BlindWatermarkTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/BlindWatermarkTemplate.php @@ -8,7 +8,6 @@ class BlindWatermarkTemplate extends ImageTemplate { private $image; private $text; private $level; - private $version; public function __construct() { parent::__construct(); @@ -17,7 +16,6 @@ class BlindWatermarkTemplate extends ImageTemplate { $this->image = ""; $this->text = ""; $this->level = ""; - $this->version = ""; } @@ -40,9 +38,6 @@ class BlindWatermarkTemplate extends ImageTemplate { public function setLevel($value) { $this->level = "/level/" . $value; } - public function setVersion($value) { - $this->version = "/version/" . $value; - } public function getType() { return $this->type; @@ -60,10 +55,6 @@ class BlindWatermarkTemplate extends ImageTemplate { return $this->level; } - public function getVersion() { - return $this->version; - } - public function queryString() { $head = "watermark/$this->markType"; @@ -80,9 +71,6 @@ class BlindWatermarkTemplate extends ImageTemplate { if($this->level){ $res .= $this->level; } - if($this->version){ - $res .= $this->version; - } if($res){ $res = $head . $res; } @@ -95,6 +83,5 @@ class BlindWatermarkTemplate extends ImageTemplate { $this->image = ""; $this->text = ""; $this->level = ""; - $this->version = ""; } } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageMogrTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageMogrTemplate.php index 0f8c24f2f..eacf67778 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageMogrTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageMogrTemplate.php @@ -2,10 +2,6 @@ namespace Qcloud\Cos\ImageParamTemplate; -/** - * Class ImageMogrTemplate imageMogr2 接口参数 - * @package Qcloud\Cos\ImageParamTemplate - */ class ImageMogrTemplate extends ImageTemplate { private $tranParams; @@ -17,139 +13,46 @@ class ImageMogrTemplate extends ImageTemplate $this->tranString = ""; } - /** - * 指定图片的宽高为原图的 Scale% - * @param $widthScale - */ public function thumbnailByScale($widthScale) { $this->tranParams[] = "/thumbnail/!" . $widthScale . "p"; } - /** - * 指定图片的宽为原图的 Scale%,高度不变 - * @param $heightScale - */ public function thumbnailByWidthScale($heightScale) { $this->tranParams[] = "/thumbnail/!" . $heightScale . "px"; } - /** - * 指定图片的高为原图的 Scale%,宽度不变 - * @param $scale - */ public function thumbnailByHeightScale($scale) { $this->tranParams[] = "/thumbnail/!x" . $scale . "p"; } - /** - * 指定目标图片宽度为 Width,高度等比缩放 - * @param $width - */ public function thumbnailByWidth($width) { $this->tranParams[] = "/thumbnail/" . $width . "x"; } - /** - * 指定目标图片高度为 Height,宽度等比缩放 - * @param $height - */ public function thumbnailByHeight($height) { $this->tranParams[] = "/thumbnail/x" . $height; } - /** - * 限定缩略图的宽度和高度的最大值分别为 Width 和 Height,进行等比缩放 - * @param $maxW - * @param $maxH - */ public function thumbnailByMaxWH($maxW, $maxH) { $this->tranParams[] = "/thumbnail/" . $maxW . "x" . $maxH; } - /** - * 限定缩略图的宽度和高度的最小值分别为 Width 和 Height,进行等比缩放 - * @param $minW - * @param $minH - */ public function thumbnailByMinWH($minW, $minH) { $this->tranParams[] = "/thumbnail/!" . $minW . "x" . $minH . "r" ; } - /** - * 忽略原图宽高比例,指定图片宽度为 Width,高度为 Height,强行缩放图片,可能导致目标图片变形 - * @param $width - * @param $height - */ public function thumbnailByWH($width, $height) { $this->tranParams[] = "/thumbnail/" . $width . "x" . $height . "!"; } - /** - * 限定缩略图的宽度和高度的最大值分别为 Width 和 Height,进行等比缩小,比例值为宽缩放比和高缩放比的较小值,如果目标宽(高)都大于原图宽(高),则不变 - * @param $width - * @param $height - */ - public function thumbnailEqualRatioReduceByWH($width, $height) { - $this->tranParams[] = "/thumbnail/{$width}x{$height}>"; - } - - /** - * 限定缩略图的宽度和高度的最大值分别为 Width 和 Height,进行等比放大,比例值为宽缩放比和高缩放比的较小值。如果目标宽(高)小于原图宽(高),则不变 - * @param $width - * @param $height - */ - public function thumbnailEqualRatioEnlargeByWH($width, $height) { - $this->tranParams[] = "/thumbnail/{$width}x{$height}<"; - } - - /** - * 等比缩放图片,缩放后的图像,总像素数量不超过 $pixel - * @param $pixel - */ public function thumbnailByPixel($pixel) { $this->tranParams[] = "/thumbnail/" . $pixel . "@"; } - /** - * 将原图缩放为指定 Width 和 Height 的矩形内的最大图片,之后使用 color 参数指定的颜色居中填充空白部分;取值0或1,0代表不使用 pad 模式,1代表使用 pad 模式 - * @param $is - */ - public function pad($is) { - $this->tranParams[] = "/pad/{$is}"; - } - - /** - * 填充颜色,缺省为白色,需设置为十六进制 RGB 格式(如 #FF0000),详情参考 RGB 编码表,需经过 URL 安全的 Base64 编码,默认值为 #3D3D3D - * @param $rgb - */ - public function color($rgb) { - $rgb = $this->ciBase64($rgb); - $this->tranParams[] = "/color/{$rgb}"; - } - - /** - * 当处理参数中携带此参数时,针对文件过大、参数超限等导致处理失败的场景,会直接返回原图而不报错 - */ - public function ignoreError() { - $this->tranParams[] = "/ignore-error/1"; - } - - /** - * 普通裁剪参数说明 操作名称:cut - * @param $width - * @param $height - * @param $dx - * @param $dy - */ public function cut($width, $height, $dx, $dy) { $this->tranParams[] = "/cut/" . $width . "x" . "$height" . "x" . $dx . "x" . $dy; } - /** - * 指定目标图片宽度为 Width,高度不变。Width 取值范围应大于0,小于原图宽度 - * @param $width - * @param string $gravity 指定操作的起点位置 - */ public function cropByWidth($width, $gravity = "") { $temp = "/crop/" . $width . "x"; if($gravity){ @@ -158,11 +61,6 @@ class ImageMogrTemplate extends ImageTemplate $this->tranParams[] = $temp; } - /** - * 指定目标图片高度为 Height,宽度不变。Height 取值范围应大于0,小于原图高度 - * @param $height - * @param string $gravity 指定操作的起点位置 - */ public function cropByHeight($height, $gravity = "") { $temp = "/crop/x" . $height; if($gravity){ @@ -171,12 +69,6 @@ class ImageMogrTemplate extends ImageTemplate $this->tranParams[] = $temp; } - /** - * 指定目标图片宽度为 Width,高度为 Height 。Width 和 Height 取值范围都应大于0,小于原图宽度/高度 - * @param $width - * @param $height - * @param string $gravity 指定操作的起点位置 - */ public function cropByWH($width, $height, $gravity = "") { $temp = "/crop/" . $width . "x" . $height; if($gravity){ @@ -185,85 +77,38 @@ class ImageMogrTemplate extends ImageTemplate $this->tranParams[] = $temp; } - /** - * 内切圆裁剪功能,radius 是内切圆的半径,取值范围为大于0且小于原图最小边一半的整数。内切圆的圆心为图片的中心。图片格式为 gif 时,不支持该参数。 - * @param $radius - */ public function iradius($radius) { $this->tranParams[] = "/iradius/" . $radius; } - /** - * 圆角裁剪功能,radius 为图片圆角边缘的半径,取值范围为大于0且小于原图最小边一半的整数。圆角与原图边缘相切。图片格式为 gif 时,不支持该参数。 - * @param $radius - */ public function rradius($radius) { $this->tranParams[] = "/rradius/" . $radius; } - /** - * 基于图片中的人脸位置进行缩放裁剪。目标图片的宽度为 Width、高度为 Height。 - * @param $width - * @param $height - */ public function scrop($width, $height) { $this->tranParams[] = "/scrop/" . $width . "x" . $height; } - /** - * 普通旋转:图片顺时针旋转角度,取值范围0 - 360,默认不旋转。 - * @param $degree - */ public function rotate($degree) { $this->tranParams[] = "/rotate/" . $degree; } - /** - * 自适应旋转:根据原图 EXIF 信息将图片自适应旋转回正。 - */ public function autoOrient() { - $this->tranParams[] = "/auto-orient"; + $this->tranParams[] = "/rotate/auto-orient"; } - /** - * 镜像翻转:flip 值为 vertical 表示垂直翻转,horizontal 表示水平翻转 - * @param $flip - */ - public function flip($flip) { - $this->tranParams[] = "/flip/" . $flip; - } - - /** - * 格式转换:目标缩略图的图片格式可为:jpg,bmp,gif,png,webp,yjpeg 等,其中 yjpeg 为数据万象针对 jpeg 格式进行的优化,本质为 jpg 格式;缺省为原图格式。 - * @param $format - */ public function format($format) { $this->tranParams[] = "/format/" . $format; } - /** - * gif 格式优化:只针对原图为 gif 格式,对 gif 图片格式进行的优化,降帧降颜色。分为以下两种情况: - * FrameNumber=1,则按照默认帧数30处理,如果图片帧数大于该帧数则截取。 - * FrameNumber 取值( 1,100 ],则将图片压缩到指定帧数 (FrameNumber)。 - * @param $frameNumber - */ public function gifOptimization($frameNumber) { $this->tranParams[] = "/cgif/" . $frameNumber; } - /** - * 输出为渐进式 jpg 格式。Mode 可为0或1。0:表示不开启渐进式;1:表示开启渐进式。该参数仅在输出图片格式为 jpg 格式时有效。如果输出非 jpg 图片格式,会忽略该参数,默认值0。 - * @param $mode - */ public function jpegInterlaceMode($mode) { $this->tranParams[] = "/interlace/" . $mode; } - /** - * 图片的绝对质量,取值范围0 - 100,默认值为原图质量;取原图质量和指定质量的最小值;后面加“!”表示强制使用指定值,例如:90!。 - * @param $value - * @param int $force - */ public function quality($value, $force = 0) { $temp = "/quality/" . $value; if($force){ @@ -272,94 +117,34 @@ class ImageMogrTemplate extends ImageTemplate $this->tranParams[] = $temp; } - /** - * 图片的最低质量,取值范围0 - 100,设置结果图的质量参数最小值。 - * 例如原图质量为85,将 lquality 设置为80后,处理结果图的图片质量为85。 - * 例如原图质量为60,将 lquality 设置为80后,处理结果图的图片质量会被提升至80。 - * @param $value - */ public function lowestQuality($value) { $this->tranParams[] = "/lquality/" . $value; } - /** - * 图片的相对质量,取值范围0 - 100,数值以原图质量为标准。例如原图质量为80,将 rquality 设置为80后,得到处理结果图的图片质量为64(80x80%)。 - * @param $value - */ public function relativelyQuality($value) { $this->tranParams[] = "/rquality/" . $value; } - /** - * 高斯模糊 - * @param $radius integer|float 模糊半径,取值范围为1 - 50 - * @param $sigma integer|float 正态分布的标准差,必须大于0 - */ public function blur($radius, $sigma) { $this->tranParams[] = "/blur/" . $radius . "x" . $sigma; } - /** - * 图片亮度调节功能,value 为亮度参数值,取值范围为[-100, 100]的整数。 - * 取值<0:降低图片亮度。 - * 取值 = 0:不调整图片亮度。 - * 取值>0:提高图片亮度。 - * @param $value - */ public function bright($value) { $this->tranParams[] = "/bright/" . $value; } - /** - * 图片对比度调节功能,value 为对比度参数值,取值范围为[-100, 100]的整数。 - * 取值<0:降低图片对比度。 - * 取值 = 0:不调整图片对比度。 - * 取值>0:提高图片对比度。 - * @param $value - */ public function contrast($value) { $this->tranParams[] = "/contrast/" . $value; } - /** - * 图片锐化功能,value 为锐化参数值,取值范围为10 - 300间的整数(推荐使用70)。参数值越大,锐化效果越明显。 - * @param $value - */ public function sharpen($value) { $this->tranParams[] = "/sharpen/" . $value; } - /** - * 将图片设置为灰度图。 value 取值为0表示不改变图片。 value 取值为1表示将图片变为灰度图。 - * @param $value - */ - public function grayscale($value) { - $this->tranParams[] = "/grayscale/" . $value; - } - - /** - * 去除图片元信息,包括 exif 信息 - */ public function strip() { $this->tranParams[] = "/strip"; } - /** - * 限制图片转换后的大小,支持以兆字节(m)和千字节(k)为单位 - * 1. 仅支持 JPG 格式的图片,可以用于限制处理后图片的大小 - * 2. 若在尾部加上!,表示用处理后的图片大小与原图大小做比较,如果处理后的图片比原图小,则返回处理后的图片,否则返回原图。例如:examplebucket-1250000000.cos.ap-shanghai.myqcloud.com/picture.jpg?imageMogr2/size-limit/15k! - * 3. 建议搭配strip参数使用,去除图片的一些冗余信息,会有更好的效果。例如:examplebucket-1250000000.cos.ap-shanghai.myqcloud.com/picture.jpg?imageMogr2/strip/format/png/size-limit/15k! - * @param $value - * @param int $compare - */ - public function sizeLimit($value, $compare = 0) { - $temp = "/size-limit/" . $value; - if($compare){ - $temp .= "!"; - } - $this->tranParams[] = $temp; - } - public function queryString() { if($this->tranParams) { $this->tranString = "imageMogr2" . implode("", $this->tranParams); diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageQrcodeTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageQrcodeTemplate.php index 1886f3e0d..606168b11 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageQrcodeTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageQrcodeTemplate.php @@ -4,68 +4,34 @@ namespace Qcloud\Cos\ImageParamTemplate; class ImageQrcodeTemplate extends ImageTemplate { - private $cover; - private $barType; - private $segment; - private $size; + private $mode; public function __construct() { parent::__construct(); - $this->cover = ""; - $this->barType = ""; - $this->segment = ""; - $this->size = ""; + $this->mode = ""; } - public function setCover($cover) { - $this->cover = "/cover/" . $cover; - } - public function getCover() { - return $this->cover; + public function setMode($mode) { + $this->mode = "/cover/" . $mode; } - public function setBarType($barType) { - $this->barType = "/bar-type/" . $barType; - } - public function getBarType() { - return $this->barType; - } - - public function setSegment($segment) { - $this->segment = "/segmente/" . $segment; - } - public function getSegment() { - return $this->segment; - } - - public function setSize($size) { - $this->size = "/size/" . $size; - } - public function getSize() { - return $this->size; + public function getMode() { + return $this->mode; } public function queryString() { - $res = "QRcode"; - if($this->cover) { - $res .= $this->cover; + $head = "QRcode"; + $res = ""; + if($this->mode) { + $res .= $this->mode; } - if($this->barType) { - $res .= $this->barType; - } - if($this->segment) { - $res .= $this->segment; - } - if($this->size) { - $res .= $this->size; + if($res) { + $res = $head . $res; } return $res; } public function resetRule() { - $this->cover = ""; - $this->barType = ""; - $this->segment = ""; - $this->size = ""; + $this->mode = ""; } } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageViewTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageViewTemplate.php index 64bfffd16..fd54f8957 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageViewTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageViewTemplate.php @@ -12,7 +12,6 @@ class ImageViewTemplate extends ImageTemplate private $height; private $format; private $quality; - private $ignoreError; public function __construct() { @@ -22,7 +21,6 @@ class ImageViewTemplate extends ImageTemplate $this->height = ""; $this->format = ""; $this->quality = ""; - $this->ignoreError = ""; } public function setMode($value) { @@ -54,10 +52,6 @@ class ImageViewTemplate extends ImageTemplate } } - public function ignoreError() { - $this->ignoreError = '/ignore-error/1'; - } - public function getMode() { return $this->mode; } @@ -96,9 +90,6 @@ class ImageViewTemplate extends ImageTemplate if($this->quality) { $res .= $this->quality; } - if($this->ignoreError) { - $res .= $this->ignoreError; - } if($res) { $res = $head . $res; } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageWatermarkTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageWatermarkTemplate.php index ee2015cc6..d9f4c5aba 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageWatermarkTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/ImageWatermarkTemplate.php @@ -6,146 +6,56 @@ class ImageWatermarkTemplate extends ImageTemplate { private $image; - private $imageKey; private $gravity; private $dx; private $dy; private $blogo; private $scatype; private $spcent; - private $dissolve; - private $batch; - private $spacing; - private $degree; public function __construct() { parent::__construct(); $this->image = ""; - $this->imageKey = ""; $this->gravity = ""; $this->dx = ""; $this->dy = ""; $this->blogo = ""; $this->scatype = ""; $this->spcent = ""; - $this->dissolve = ""; - $this->batch = ""; - $this->spacing = ""; - $this->degree = ""; } - /** - * 水印图片地址,需要经过 URL 安全的 Base64 编码。 - * @param $value - */ public function setImage($value) { $this->image = "/image/" . $this->ciBase64($value); } - /** - * 如果您在添加水印时不希望暴露水印所在的图片地址,可使用该参数。 - * @param $value - */ - public function setImageKey($value) { - $this->imageKey = "/image_key/" . $this->ciBase64($value); - } - - /** - * 图片水印位置,九宫格位置(参考九宫格方位图 ),默认值 SouthEast - * @param $value - */ public function setGravity($value) { $this->gravity = "/gravity/" . $value; } - /** - * 水平(横轴)边距,单位为像素,缺省值为0 - * @param $value - */ public function setDx($value) { $this->dx = "/dx/" . $value; } - /** - * 垂直(纵轴)边距,单位为像素,默认值为0 - * @param $value - */ public function setDy($value) { $this->dy = "/dy/" . $value; } - /** - * 水印图适配功能,适用于水印图尺寸过大的场景(如水印墙)。共有两种类型: - * 当 blogo 设置为1时,水印图会被缩放至与原图相似大小后添加 - * 当 blogo 设置为2时,水印图会被直接裁剪至与原图相似大小后添加 - * @param $value - */ public function setBlogo($value) { $this->blogo = "/blogo/" . $value; } - /** - * 根据原图的大小,缩放调整水印图的大小: - * 当 scatype 设置为1时,按原图的宽缩放 - * 当 scatype 设置为2时,按原图的高缩放 - * 当 scatype 设置为3时,按原图的整体面积缩放 - * @param $value - */ public function setScatype($value) { $this->scatype = "/scatype/" . $value; } - /** - * 与 scatype 搭配使用: - * 当 scatype 设置为1时,该有效值为[1,1000],单位为千分比 - * 当 scatype 设置为2时,该有效值为[1,1000],单位为千分比 - * 当 scatype 设置为3时,该有效值为[1,250],单位为千分比。 - * @param $value - */ public function setSpcent($value) { $this->spcent = "/spcent/" . $value; } - /** - * 图片水印的透明度,取值为1 - 100,默认90(90%不透明度) - * @param $value - */ - public function setDissolve($value) { - $this->dissolve = "/dissolve/" . $value; - } - - /** - * 平铺水印功能,可将图片水印平铺至整张图片。值为1时,表示开启平铺水印功能 - * @param $value - */ - public function setBatch($value) { - $this->batch = "/batch/" . $value; - } - - /** - * 平铺水印功能,宽高百分比 - * @param $value - */ - public function setSpacing($value) { - $this->spacing = "/spacing/" . $value; - } - - /** - * 当 batch 值为1时生效。图片水印的旋转角度设置,取值范围为0 - 360,默认0 - * @param $value - */ - public function setDegree($value) { - $this->degree = "/degree/" . $value; - } - public function getImage() { return $this->image; } - public function getImageKey() { - return $this->imageKey; - } - public function getGravity() { return $this->gravity; } @@ -170,31 +80,12 @@ class ImageWatermarkTemplate extends ImageTemplate return $this->spcent; } - public function getDissolve() { - return $this->dissolve; - } - - public function getBatch() { - return $this->batch; - } - - public function getSpacing() { - return $this->spacing; - } - - public function getDegree() { - return $this->degree; - } - public function queryString() { $head = "watermark/1"; $res = ""; if($this->image) { $res .= $this->image; } - if($this->imageKey) { - $res .= $this->imageKey; - } if($this->gravity) { $res .= $this->gravity; } @@ -213,18 +104,6 @@ class ImageWatermarkTemplate extends ImageTemplate if($this->spcent) { $res .= $this->spcent; } - if($this->dissolve) { - $res .= $this->dissolve; - } - if($this->batch) { - $res .= $this->batch; - } - if($this->spacing) { - $res .= $this->spacing; - } - if($this->degree) { - $res .= $this->degree; - } if($res) { $res = $head . $res; } @@ -233,16 +112,11 @@ class ImageWatermarkTemplate extends ImageTemplate public function resetRule() { $this->image = ""; - $this->imageKey = ""; $this->gravity = ""; $this->dx = ""; $this->dy = ""; $this->blogo = ""; $this->scatype = ""; $this->spcent = ""; - $this->dissolve = ""; - $this->batch = ""; - $this->spacing = ""; - $this->degree = ""; } } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/PicOperationsTransformation.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/PicOperationsTransformation.php index a2f10deae..b10f5d5a7 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/PicOperationsTransformation.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/PicOperationsTransformation.php @@ -2,10 +2,6 @@ namespace Qcloud\Cos\ImageParamTemplate; -/** - * Class PicOperationsTransformation 图片处理参数 Pic-Operations - * @package Qcloud\Cos\ImageParamTemplate - */ class PicOperationsTransformation { private $isPicInfo; private $rules; diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/TextWatermarkTemplate.php b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/TextWatermarkTemplate.php index 0f417ad69..f1561a753 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/TextWatermarkTemplate.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ImageParamTemplate/TextWatermarkTemplate.php @@ -16,11 +16,7 @@ class TextWatermarkTemplate extends ImageTemplate private $dx; private $dy; private $batch; - private $spacing; private $degree; - private $shadow; - private $scatype; - private $spcent; public function __construct() { parent::__construct(); @@ -33,11 +29,7 @@ class TextWatermarkTemplate extends ImageTemplate $this->dx = ""; $this->dy = ""; $this->batch = ""; - $this->spacing = ""; $this->degree = ""; - $this->shadow = ""; - $this->scatype = ""; - $this->spcent = ""; } public function setText($value) { @@ -76,26 +68,10 @@ class TextWatermarkTemplate extends ImageTemplate $this->batch = "/batch/" . $value; } - public function setSpacing($value) { - $this->spacing = "/spacing/" . $value; - } - public function setDegree($value) { $this->degree = "/degree/" . $value; } - public function setShadow($value) { - $this->shadow = "/shadow/" . $value; - } - - public function setScatype($value) { - $this->scatype = "/scatype/" . $value; - } - - public function setSpcent($value) { - $this->spcent = "/spcent/" . $value; - } - public function getText() { return $this->text; } @@ -132,26 +108,10 @@ class TextWatermarkTemplate extends ImageTemplate return $this->batch; } - public function getSpacing() { - return $this->spacing; - } - public function getDegree() { return $this->degree; } - public function getShadow() { - return $this->shadow; - } - - public function getScatype() { - return $this->scatype; - } - - public function getSpcent() { - return $this->spcent; - } - public function queryString() { $head = "watermark/2"; $res = ""; @@ -182,21 +142,9 @@ class TextWatermarkTemplate extends ImageTemplate if($this->batch) { $res .= $this->batch; } - if($this->spacing) { - $res .= $this->spacing; - } if($this->degree) { $res .= $this->degree; } - if($this->shadow) { - $res .= $this->shadow; - } - if($this->scatype) { - $res .= $this->scatype; - } - if($this->spcent) { - $res .= $this->spcent; - } if($res) { $res = $head . $res; } @@ -213,10 +161,6 @@ class TextWatermarkTemplate extends ImageTemplate $this->dx = ""; $this->dy = ""; $this->batch = ""; - $this->spacing = ""; $this->degree = ""; - $this->shadow = ""; - $this->scatype = ""; - $this->spcent = ""; } } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/MultipartUpload.php b/src/vendor/qcloud/cos-sdk-v5/src/MultipartUpload.php index 9967efa09..2eec9c0c4 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/MultipartUpload.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/MultipartUpload.php @@ -18,10 +18,6 @@ class MultipartUpload { private $progress; private $totalSize; private $uploadedSize; - private $concurrency; - private $partNumberList; - private $needMd5; - private $retry; public function __construct($client, $body, $options = array()) { $minPartSize = $options['PartSize']; @@ -39,7 +35,6 @@ class MultipartUpload { $this->needMd5 = isset($options['ContentMD5']) ? $options['ContentMD5'] : true; $this->retry = isset($options['Retry']) ? $options['Retry'] : 3; } - public function performUploading() { $uploadId= $this->initiateMultipartUpload(); $this->uploadParts($uploadId); @@ -56,7 +51,6 @@ class MultipartUpload { ); } - public function uploadParts($uploadId) { $uploadRequests = function ($uploadId) { $partNumber = 1; @@ -169,4 +163,5 @@ class MultipartUpload { $result = $this->client->createMultipartUpload($this->options); return $result['UploadId']; } + } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/RangeDownload.php b/src/vendor/qcloud/cos-sdk-v5/src/RangeDownload.php index 425a63f71..77f50f7c4 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/RangeDownload.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/RangeDownload.php @@ -14,27 +14,21 @@ class RangeDownload { private $progress; private $totalSize; private $resumableJson; - private $concurrency; - private $partNumberList; - private $downloadedSize; - private $saveAs; - private $resumableTaskFile; - private $resumableDownload; - private $resumableJsonLocal; - private $fp; - private $fp_resume; public function __construct( $client, $contentLength, $saveAs, $options = array() ) { $this->client = $client; $this->options = $options; $this->partSize = isset( $options['PartSize'] ) ? $options['PartSize'] : self::DEFAULT_PART_SIZE; $this->concurrency = isset( $options['Concurrency'] ) ? $options['Concurrency'] : 10; - $this->progress = isset( $options['Progress'] ) ? $options['Progress'] : function( $totalSize, $downloadedSize ) {}; + $this->progress = isset( $options['Progress'] ) ? $options['Progress'] : function( $totalSize, $downloadedSize ) { + } + ; $this->parts = []; $this->partNumberList = []; $this->downloadedSize = 0; $this->totalSize = $contentLength; $this->saveAs = $saveAs; + $this->resumableJson = []; $this->resumableJson = isset( $options['ResumableJson'] ) ? $options['ResumableJson'] : []; unset( $options['ResumableJson'] ); $this->resumableTaskFile = isset( $options['ResumableTaskFile'] ) ? $options['ResumableTaskFile'] : $saveAs . '.cosresumabletask'; @@ -147,4 +141,5 @@ class RangeDownload { $promise = $pool->promise(); $promise->wait(); } + } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/ResultTransformer.php b/src/vendor/qcloud/cos-sdk-v5/src/ResultTransformer.php index c3ca71812..0bdb245c4 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/ResultTransformer.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/ResultTransformer.php @@ -18,7 +18,7 @@ class ResultTransformer { public function writeDataToLocal(CommandInterface $command, RequestInterface $request, ResponseInterface $response) { $action = $command->getName(); - if ($action == "GetObject" || $action == "GetSnapshot" || $action == "ImageRepairProcess") { + if ($action == "GetObject" || $action == "GetSnapshot") { if (isset($command['SaveAs'])) { $fp = fopen($command['SaveAs'], "wb"); $stream = $response->getBody(); @@ -56,10 +56,7 @@ class ResultTransformer { if ($command['Bucket'] != null && $result['Bucket'] == null) { $result['Bucket'] = $command['Bucket']; } - $result['Location'] = $request->getHeader('Host')[0] . $request->getUri()->getPath(); - if ($this->config['locationWithScheme']) { - $result['Location'] = $this->config['scheme'] . '://' . $result['Location']; - } + $result['Location'] = $request->getHeader("Host")[0] . $request->getUri()->getPath(); return $result; } @@ -86,9 +83,6 @@ class ResultTransformer { $length = intval($result['ContentLength']); if($length > 0){ $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); $xmlData = json_decode(json_encode($obj),true); if ($picRuleSize == 1 && isset($xmlData['ProcessResults']['Object'])){ @@ -100,75 +94,16 @@ class ResultTransformer { } } - if ($action == "GetBucketGuetzli") { + if ($action == "GetBucketGuetzli" ) { $length = intval($result['ContentLength']); if($length > 0){ $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); $arr = json_decode(json_encode($obj),true); $result['GuetzliStatus'] = isset($arr[0]) ? $arr[0] : ''; } } - if ($action == "GetCiService") { - $length = intval($result['ContentLength']); - if($length > 0){ - $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } - $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); - $arr = json_decode(json_encode($obj),true); - $result['CIStatus'] = isset($arr[0]) ? $arr[0] : ''; - unset($result['Body']); - } - } - - if ($action == "GetOriginProtect") { - $length = intval($result['ContentLength']); - if($length > 0){ - $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } - $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); - $arr = json_decode(json_encode($obj),true); - $result['OriginProtectStatus'] = isset($arr[0]) ? $arr[0] : ''; - unset($result['Body']); - } - } - - if ($action == "GetHotLink") { - $length = intval($result['ContentLength']); - if($length > 0){ - $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } - $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); - $arr = json_decode(json_encode($obj),true); - $result['Hotlink'] = $arr; - unset($result['Body']); - } - } - - if ($action == "AutoTranslationBlockProcess") { - $length = intval($result['ContentLength']); - if($length > 0){ - $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } - $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); - $arr = json_decode(json_encode($obj),true); - $result['TranslationResult'] = isset($arr[0]) ? $arr[0] : ''; - unset($result['Body']); - } - } - $xml2JsonActions = array( 'CreateMediaTranscodeJobs' => 1, 'CreateMediaJobs' => 1, @@ -183,52 +118,14 @@ class ResultTransformer { 'CreateMediaVideoProcessJobs' => 1, 'CreateMediaVideoMontageJobs' => 1, 'CreateMediaAnimationJobs' => 1, - 'CreateMediaPicProcessJobs' => 1, - 'CreateMediaSegmentJobs' => 1, - 'CreateMediaVideoTagJobs' => 1, - 'CreateMediaSuperResolutionJobs' => 1, - 'CreateMediaSDRtoHDRJobs' => 1, - 'CreateMediaDigitalWatermarkJobs' => 1, - 'CreateMediaExtractDigitalWatermarkJobs' => 1, - 'GetWorkflowInstance' => 1, - 'CreateMediaTranscodeTemplate' => 1, - 'UpdateMediaTranscodeTemplate' => 1, - 'CreateMediaHighSpeedHdTemplate' => 1, - 'UpdateMediaHighSpeedHdTemplate' => 1, - 'CreateMediaAnimationTemplate' => 1, - 'UpdateMediaAnimationTemplate' => 1, - 'CreateMediaConcatTemplate' => 1, - 'UpdateMediaConcatTemplate' => 1, - 'CreateMediaVideoProcessTemplate' => 1, - 'UpdateMediaVideoProcessTemplate' => 1, - 'CreateMediaVideoMontageTemplate' => 1, - 'UpdateMediaVideoMontageTemplate' => 1, - 'CreateMediaVoiceSeparateTemplate' => 1, - 'UpdateMediaVoiceSeparateTemplate' => 1, - 'CreateMediaSuperResolutionTemplate' => 1, - 'UpdateMediaSuperResolutionTemplate' => 1, - 'CreateMediaPicProcessTemplate' => 1, - 'UpdateMediaPicProcessTemplate' => 1, - 'CreateMediaWatermarkTemplate' => 1, - 'UpdateMediaWatermarkTemplate' => 1, - 'CreateInventoryTriggerJob' => 1, - 'DescribeInventoryTriggerJobs' => 1, - 'DescribeInventoryTriggerJob' => 1, - 'CreateMediaNoiseReductionJobs' => 1, - 'CreateMediaQualityEstimateJobs' => 1, - 'CreateMediaStreamExtractJobs' => 1, ); if (key_exists($action, $xml2JsonActions)) { $length = intval($result['ContentLength']); if($length > 0){ $content = $this->geCiContentInfo($result, $length); - if (version_compare(PHP_VERSION, '8.0.0', '<')) { - libxml_disable_entity_loader(true); - } $obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); $xmlData = json_decode(json_encode($obj),true); $result['Response'] = $xmlData; - unset($result['Body']); } } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Serializer.php b/src/vendor/qcloud/cos-sdk-v5/src/Serializer.php index 915e03bd3..1999e1b7d 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Serializer.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Serializer.php @@ -20,8 +20,7 @@ class Serializer extends DefaultSerializer array $requestLocations = [] ) { // Override Guzzle's body location as it isn't raw binary data - $requestLocations['body'] = new Request\BodyLocation(); - $requestLocations['xml'] = new Request\XmlLocation(); + $requestLocations['body'] = new Request\BodyLocation; parent::__construct($description, $requestLocations); } /** diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Service.php b/src/vendor/qcloud/cos-sdk-v5/src/Service.php index 802d79e70..2fee88501 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Service.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Service.php @@ -1562,7 +1562,7 @@ class Service { ), ) ), - // 设置存储桶(Bucket)的访问权限 (Access Control List, ACL) + // 设置存储桶(Bucket)的访问权限(Access Control List, ACL) 'PutBucketAcl' => array( 'httpMethod' => 'PUT', 'uri' => '/{Bucket}?acl', @@ -3485,23 +3485,6 @@ class Service { 'type' => 'string', 'location' => 'xml', ), - 'UserInfo' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml', ), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml', ), - 'AppId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Room' => array( 'type' => 'string', 'location' => 'xml', ), - 'IP' => array( 'type' => 'string', 'location' => 'xml', ), - 'Type' => array( 'type' => 'string', 'location' => 'xml', ), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml', ), - 'Gender' => array( 'type' => 'string', 'location' => 'xml', ), - 'Level' => array( 'type' => 'string', 'location' => 'xml', ), - 'Role' => array( 'type' => 'string', 'location' => 'xml', ), - ), - ), ), ), 'Conf' => array( @@ -3512,19 +3495,6 @@ class Service { 'Callback' => array( 'type' => 'string', 'location' => 'xml', ), 'BizType' => array( 'type' => 'string', 'location' => 'xml', ), 'CallbackVersion' => array( 'type' => 'string', 'location' => 'xml', ), - 'CallbackType' => array( 'type' => 'integer', 'location' => 'xml', ), - 'Freeze' => array( - 'location' => 'xml', - 'type' => 'object', - 'properties' => array( - 'PornScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AdsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'IllegalScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'AbuseScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'PoliticsScore' => array( 'type' => 'integer', 'location' => 'xml', ), - 'TerrorismScore' => array( 'type' => 'integer', 'location' => 'xml', ), - ), - ), ), ), ), @@ -3710,7 +3680,6 @@ class Service { 'DescribeDocProcessJob' => Descriptions::DescribeDocProcessJob(), // 查询文档转码任务 'GetDescribeDocProcessJobs' => Descriptions::GetDescribeDocProcessJobs(), // 拉取符合条件的文档转码任务 'DetectImage' => Descriptions::DetectImage(), // 图片审核 - 'DetectImageUrl' => Descriptions::DetectImageUrl(), // 图片审核 'DetectImages' => Descriptions::DetectImages(), // 图片审核-批量 'DetectVirus' => Descriptions::DetectVirus(), // 云查毒 'GetDetectVirusResult' => Descriptions::GetDetectVirusResult(), // 查询病毒检测任务结果 @@ -3727,154 +3696,6 @@ class Service { 'CreateMediaVideoProcessJobs' => Descriptions::CreateMediaVideoProcessJobs(), // 提交视频增强任务 'CreateMediaVideoMontageJobs' => Descriptions::CreateMediaVideoMontageJobs(), // 提交精彩集锦任务 'CreateMediaAnimationJobs' => Descriptions::CreateMediaAnimationJobs(), // 提交动图任务 - 'CreateMediaPicProcessJobs' => Descriptions::CreateMediaPicProcessJobs(), // 提交图片处理任务 - 'CreateMediaSegmentJobs' => Descriptions::CreateMediaSegmentJobs(), // 提交转封装任务 - 'CreateMediaVideoTagJobs' => Descriptions::CreateMediaVideoTagJobs(), // 提交视频标签任务 - 'CreateMediaSuperResolutionJobs' => Descriptions::CreateMediaSuperResolutionJobs(), // 提交超分辨率任务 - 'CreateMediaSDRtoHDRJobs' => Descriptions::CreateMediaSDRtoHDRJobs(), // 提交 SDR to HDR 任务 - 'CreateMediaDigitalWatermarkJobs' => Descriptions::CreateMediaDigitalWatermarkJobs(), // 嵌入数字水印任务(添加水印) - 'CreateMediaExtractDigitalWatermarkJobs' => Descriptions::CreateMediaExtractDigitalWatermarkJobs(), // 提取数字水印任务(提取水印) - 'DetectLiveVideo' => Descriptions::DetectLiveVideo(), // 直播流审核 - 'CancelLiveVideoAuditing' => Descriptions::CancelLiveVideoAuditing(), // 取消直播流审核 - 'OpticalOcrRecognition' => Descriptions::OpticalOcrRecognition(), // 通用文字识别 - 'TriggerWorkflow' => Descriptions::TriggerWorkflow(), // 手动触发工作流 - 'GetWorkflowInstances' => Descriptions::GetWorkflowInstances(), // 获取工作流实例列表 - 'GetWorkflowInstance' => Descriptions::GetWorkflowInstance(), // 获取工作流实例详情 - 'CreateMediaSnapshotTemplate' => Descriptions::CreateMediaSnapshotTemplate(), // 新增截图模板 - 'UpdateMediaSnapshotTemplate' => Descriptions::UpdateMediaSnapshotTemplate(), // 更新截图模板 - 'CreateMediaTranscodeTemplate' => Descriptions::CreateMediaTranscodeTemplate(), // 新增转码模板 - 'UpdateMediaTranscodeTemplate' => Descriptions::UpdateMediaTranscodeTemplate(), // 更新转码模板 - 'CreateMediaHighSpeedHdTemplate' => Descriptions::CreateMediaHighSpeedHdTemplate(), // 新增极速高清转码模板 - 'UpdateMediaHighSpeedHdTemplate' => Descriptions::UpdateMediaHighSpeedHdTemplate(), // 更新极速高清转码模板 - 'CreateMediaAnimationTemplate' => Descriptions::CreateMediaAnimationTemplate(), // 新增动图模板 - 'UpdateMediaAnimationTemplate' => Descriptions::UpdateMediaAnimationTemplate(), // 更新动图模板 - 'CreateMediaConcatTemplate' => Descriptions::CreateMediaConcatTemplate(), // 新增拼接模板 - 'UpdateMediaConcatTemplate' => Descriptions::UpdateMediaConcatTemplate(), // 更新拼接模板 - 'CreateMediaVideoProcessTemplate' => Descriptions::CreateMediaVideoProcessTemplate(), // 新增视频增强模板 - 'UpdateMediaVideoProcessTemplate' => Descriptions::UpdateMediaVideoProcessTemplate(), // 更新视频增强模板 - 'CreateMediaVideoMontageTemplate' => Descriptions::CreateMediaVideoMontageTemplate(), // 新增精彩集锦模板 - 'UpdateMediaVideoMontageTemplate' => Descriptions::UpdateMediaVideoMontageTemplate(), // 更新精彩集锦模板 - 'CreateMediaVoiceSeparateTemplate' => Descriptions::CreateMediaVoiceSeparateTemplate(), // 新增人声分离模板 - 'UpdateMediaVoiceSeparateTemplate' => Descriptions::UpdateMediaVoiceSeparateTemplate(), // 更新人声分离模板 - 'CreateMediaSuperResolutionTemplate' => Descriptions::CreateMediaSuperResolutionTemplate(), // 新增超分辨率模板 - 'UpdateMediaSuperResolutionTemplate' => Descriptions::UpdateMediaSuperResolutionTemplate(), // 更新超分辨率模板 - 'CreateMediaPicProcessTemplate' => Descriptions::CreateMediaPicProcessTemplate(), // 新增图片处理模板 - 'UpdateMediaPicProcessTemplate' => Descriptions::UpdateMediaPicProcessTemplate(), // 更新图片处理模板 - 'CreateMediaWatermarkTemplate' => Descriptions::CreateMediaWatermarkTemplate(), // 新增水印模板 - 'UpdateMediaWatermarkTemplate' => Descriptions::UpdateMediaWatermarkTemplate(), // 更新水印模板 - 'DescribeMediaTemplates' => Descriptions::DescribeMediaTemplates(), // 查询模板列表 - 'DescribeWorkflow' => Descriptions::DescribeWorkflow(), // 搜索工作流 - 'DeleteWorkflow' => Descriptions::DeleteWorkflow(), // 删除工作流 - 'CreateInventoryTriggerJob' => Descriptions::CreateInventoryTriggerJob(), // 触发批量存量任务 - 'DescribeInventoryTriggerJobs' => Descriptions::DescribeInventoryTriggerJobs(), // 批量拉取存量任务 - 'DescribeInventoryTriggerJob' => Descriptions::DescribeInventoryTriggerJob(), // 查询存量任务 - 'CancelInventoryTriggerJob' => Descriptions::CancelInventoryTriggerJob(), // 取消存量任务 - 'CreateMediaNoiseReductionJobs' => Descriptions::CreateMediaNoiseReductionJobs(), // 提交音频降噪任务 - 'ImageRepairProcess' => Descriptions::ImageRepairProcess(), // 图片水印修复 - 'ImageDetectCarProcess' => Descriptions::ImageDetectCarProcess(), // 车辆车牌检测 - 'ImageAssessQualityProcess' => Descriptions::ImageAssessQualityProcess(), // 图片质量评估 - 'ImageSearchOpen' => Descriptions::ImageSearchOpen(), // 开通以图搜图 - 'ImageSearchAdd' => Descriptions::ImageSearchAdd(), // 添加图库图片 - 'ImageSearch' => Descriptions::ImageSearch(), // 图片搜索接口 - 'ImageSearchDelete' => Descriptions::ImageSearchDelete(), // 图片搜索接口 - 'BindCiService' => Descriptions::BindCiService(), // 绑定数据万象服务 - 'GetCiService' => Descriptions::GetCiService(), // 查询数据万象服务 - 'UnBindCiService' => Descriptions::UnBindCiService(), // 解绑数据万象服务 - 'GetHotLink' => Descriptions::GetHotLink(), // 查询防盗链 - 'AddHotLink' => Descriptions::AddHotLink(), // 查询防盗链 - 'OpenOriginProtect' => Descriptions::OpenOriginProtect(), // 开通原图保护 - 'GetOriginProtect' => Descriptions::GetOriginProtect(), // 查询原图保护状态 - 'CloseOriginProtect' => Descriptions::CloseOriginProtect(), // 关闭原图保护 - 'ImageDetectFace' => Descriptions::ImageDetectFace(), // 人脸检测 - 'ImageFaceEffect' => Descriptions::ImageFaceEffect(), // 人脸特效 - 'ImageUrlFaceEffect' => Descriptions::ImageUrlFaceEffect(), // 人脸特效 - 'IDCardOCR' => Descriptions::IDCardOCR(), // 身份证识别 - 'IDCardOCRByUpload' => Descriptions::IDCardOCRByUpload(), // 身份证识别-上传时处理 - 'GetLiveCode' => Descriptions::GetLiveCode(), // 获取数字验证码 - 'GetActionSequence' => Descriptions::GetActionSequence(), // 获取动作顺序 - 'DescribeDocProcessBuckets' => Descriptions::DescribeDocProcessBuckets(), // 查询文档预览开通状态 - 'UpdateDocProcessQueue' => Descriptions::UpdateDocProcessQueue(), // 更新文档转码队列 - 'CreateMediaQualityEstimateJobs' => Descriptions::CreateMediaQualityEstimateJobs(), // 提交视频质量评分任务 - 'CreateMediaStreamExtractJobs' => Descriptions::CreateMediaStreamExtractJobs(), // 提交音视频流分离任务 - 'FileJobs4Hash' => Descriptions::FileJobs4Hash(), // 哈希值计算同步请求 - 'OpenFileProcessService' => Descriptions::OpenFileProcessService(), // 开通文件处理服务 - 'GetFileProcessQueueList' => Descriptions::GetFileProcessQueueList(), // 搜索文件处理队列 - 'UpdateFileProcessQueue' => Descriptions::UpdateFileProcessQueue(), // 更新文件处理的队列 - 'CreateFileHashCodeJobs' => Descriptions::CreateFileHashCodeJobs(), // 提交哈希值计算任务 - 'GetFileHashCodeResult' => Descriptions::GetFileHashCodeResult(), // 查询哈希值计算结果 - 'CreateFileUncompressJobs' => Descriptions::CreateFileUncompressJobs(), // 提交文件解压任务 - 'GetFileUncompressResult' => Descriptions::GetFileUncompressResult(), // 查询文件解压结果 - 'CreateFileCompressJobs' => Descriptions::CreateFileCompressJobs(), // 提交多文件打包压缩任务 - 'GetFileCompressResult' => Descriptions::GetFileCompressResult(), // 查询多文件打包压缩结果 - 'CreateM3U8PlayListJobs' => Descriptions::CreateM3U8PlayListJobs(), // 获取指定hls/m3u8文件指定时间区间内的ts资源 - 'GetPicQueueList' => Descriptions::GetPicQueueList(), // 搜索图片处理队列 - 'UpdatePicQueue' => Descriptions::UpdatePicQueue(), // 更新图片处理队列 - 'GetPicBucketList' => Descriptions::GetPicBucketList(), // 查询图片处理服务状态 - 'GetAiBucketList' => Descriptions::GetAiBucketList(), // 查询 AI 内容识别服务状态 - 'OpenAiService' => Descriptions::OpenAiService(), // 开通 AI 内容识别 - 'CloseAiService' => Descriptions::CloseAiService(), // 关闭AI内容识别服务 - 'GetAiQueueList' => Descriptions::GetAiQueueList(), // 搜索 AI 内容识别队列 - 'UpdateAiQueue' => Descriptions::UpdateAiQueue(), // 更新 AI 内容识别队列 - 'CreateMediaTranscodeProTemplate' => Descriptions::CreateMediaTranscodeProTemplate(), // 创建音视频转码 pro 模板 - 'UpdateMediaTranscodeProTemplate' => Descriptions::UpdateMediaTranscodeProTemplate(), // 更新音视频转码 pro 模板 - 'CreateVoiceTtsTemplate' => Descriptions::CreateVoiceTtsTemplate(), // 创建语音合成模板 - 'UpdateVoiceTtsTemplate' => Descriptions::UpdateVoiceTtsTemplate(), // 更新语音合成模板 - 'CreateMediaSmartCoverTemplate' => Descriptions::CreateMediaSmartCoverTemplate(), // 创建智能封面模板 - 'UpdateMediaSmartCoverTemplate' => Descriptions::UpdateMediaSmartCoverTemplate(), // 更新智能封面模板 - 'CreateVoiceSpeechRecognitionTemplate' => Descriptions::CreateVoiceSpeechRecognitionTemplate(), // 创建语音识别模板 - 'UpdateVoiceSpeechRecognitionTemplate' => Descriptions::UpdateVoiceSpeechRecognitionTemplate(), // 更新语音识别模板 - 'CreateVoiceTtsJobs' => Descriptions::CreateVoiceTtsJobs(), // 提交一个语音合成任务 - 'CreateAiTranslationJobs' => Descriptions::CreateAiTranslationJobs(), // 提交一个翻译任务 - 'CreateVoiceSpeechRecognitionJobs' => Descriptions::CreateVoiceSpeechRecognitionJobs(), // 提交一个语音识别任务 - 'CreateAiWordsGeneralizeJobs' => Descriptions::CreateAiWordsGeneralizeJobs(), // 提交一个分词任务 - 'CreateMediaVideoEnhanceJobs' => Descriptions::CreateMediaVideoEnhanceJobs(), // 提交画质增强任务 - 'CreateMediaVideoEnhanceTemplate' => Descriptions::CreateMediaVideoEnhanceTemplate(), // 创建画质增强模板 - 'UpdateMediaVideoEnhanceTemplate' => Descriptions::UpdateMediaVideoEnhanceTemplate(), // 更新画质增强模板 - 'OpenImageSlim' => Descriptions::OpenImageSlim(), // 开通图片瘦身 - 'CloseImageSlim' => Descriptions::CloseImageSlim(), // 关闭图片瘦身 - 'GetImageSlim' => Descriptions::GetImageSlim(), // 查询图片瘦身状态 - 'AutoTranslationBlockProcess' => Descriptions::AutoTranslationBlockProcess(), // 实时文字翻译 - 'RecognizeLogoProcess' => Descriptions::RecognizeLogoProcess(), // Logo 识别 - 'DetectLabelProcess' => Descriptions::DetectLabelProcess(), // 图片标签 - 'AIGameRecProcess' => Descriptions::AIGameRecProcess(), // 游戏场景识别 - 'AIBodyRecognitionProcess' => Descriptions::AIBodyRecognitionProcess(), // 人体识别 - 'DetectPetProcess' => Descriptions::DetectPetProcess(), // 宠物识别 - 'AILicenseRecProcess' => Descriptions::AILicenseRecProcess(), // 卡证识别 - 'CreateMediaTargetRecTemplate' => Descriptions::CreateMediaTargetRecTemplate(), // 创建视频目标检测模板 - 'UpdateMediaTargetRecTemplate' => Descriptions::UpdateMediaTargetRecTemplate(), // 更新视频目标检测模板 - 'CreateMediaTargetRecJobs' => Descriptions::CreateMediaTargetRecJobs(), // 提交视频目标检测任务 - 'CreateMediaSegmentVideoBodyJobs' => Descriptions::CreateMediaSegmentVideoBodyJobs(), // 提交视频人像抠图任务 - 'OpenAsrService' => Descriptions::OpenAsrService(), //开通智能语音服务 - 'GetAsrBucketList' => Descriptions::GetAsrBucketList(), // 查询智能语音服务 - 'CloseAsrService' => Descriptions::CloseAsrService(), // 关闭智能语音服务 - 'GetAsrQueueList' => Descriptions::GetAsrQueueList(), // 查询智能语音队列 - 'UpdateAsrQueue' => Descriptions::UpdateAsrQueue(), // 更新智能语音队列 - 'CreateMediaNoiseReductionTemplate' => Descriptions::CreateMediaNoiseReductionTemplate(), // 创建音频降噪模板 - 'UpdateMediaNoiseReductionTemplate' => Descriptions::UpdateMediaNoiseReductionTemplate(), // 更新音频降噪模板 - 'CreateVoiceSoundHoundJobs' => Descriptions::CreateVoiceSoundHoundJobs(), // 提交听歌识曲任务 - 'CreateVoiceVocalScoreJobs' => Descriptions::CreateVoiceVocalScoreJobs(), // 提交音乐评分任务 - 'CreateDataset' => Descriptions::CreateDataset(), // 创建数据集 - 'CreateDatasetBinding' => Descriptions::CreateDatasetBinding(), // 绑定存储桶与数据集 - 'CreateFileMetaIndex' => Descriptions::CreateFileMetaIndex(), // 创建元数据索引 - 'DatasetFaceSearch' => Descriptions::DatasetFaceSearch(), // 人脸搜索 - 'DatasetSimpleQuery' => Descriptions::DatasetSimpleQuery(), // 简单查询 - 'DeleteDataset' => Descriptions::DeleteDataset(), // 删除数据集 - 'DeleteDatasetBinding' => Descriptions::DeleteDatasetBinding(), // 解绑存储桶与数据集 - 'DeleteFileMetaIndex' => Descriptions::DeleteFileMetaIndex(), // 删除元数据索引 - 'DescribeDataset' => Descriptions::DescribeDataset(), // 查询数据集 - 'DescribeDatasetBinding' => Descriptions::DescribeDatasetBinding(), // 查询数据集与存储桶的绑定关系 - 'DescribeDatasetBindings' => Descriptions::DescribeDatasetBindings(), // 查询绑定关系列表 - 'DescribeDatasets' => Descriptions::DescribeDatasets(), // 列出数据集 - 'DescribeFileMetaIndex' => Descriptions::DescribeFileMetaIndex(), // 查询元数据索引 - 'SearchImage' => Descriptions::SearchImage(), // 图像检索 - 'UpdateDataset' => Descriptions::UpdateDataset(), // 更新数据集 - 'UpdateFileMetaIndex' => Descriptions::UpdateFileMetaIndex(), // 更新元数据索引 - 'ZipFilePreview' => Descriptions::ZipFilePreview(), // 压缩包预览同步请求 - 'GetHLSPlayKey' => Descriptions::GetHLSPlayKey(), // 获取hls播放密钥 - 'PostWatermarkJobs' => Descriptions::PostWatermarkJobs(), // 视频明水印-提交任务 - 'GeneratePlayList' => Descriptions::GeneratePlayList(), // 生成播放列表 - 'CreateWatermarkTemplate' => Descriptions::CreateWatermarkTemplate(), // 创建明水印模板 - ), 'models' => array( 'AbortMultipartUploadOutput' => array( @@ -5666,21 +5487,11 @@ class Service { 'items' => array( 'type' => 'object', 'properties' => array( - 'Bucket' => array( - 'type' => 'array', - 'items' => array( - 'type' => 'object', - 'items' => array( - 'properties' => array( - 'Name' => array( - 'type' => 'string', - ), - 'CreationDate' => array( - 'type' => 'string', - ), - ), - ), - ) + 'Name' => array( + 'type' => 'string', + ), + 'CreationDate' => array( + 'type' => 'string', ), ), ), @@ -6188,14 +5999,6 @@ class Service { 'location' => 'header', 'sentAs' => 'x-cos-request-id', ), - 'BucketAzType' => array( - 'location' => 'header', - 'sentAs' => 'x-cos-bucket-az-type', // undefined 或 MAZ - ), - 'BucketArch' => array( - 'location' => 'header', - 'sentAs' => 'x-cos-bucket-arch', // undefined 或 OFS - ), ), ), 'SelectObjectContentOutput' => array( @@ -6711,7 +6514,6 @@ class Service { 'CreationTime' => array( 'type' => 'string', 'location' => 'xml',), 'Content' => array( 'type' => 'string', 'location' => 'xml',), 'Label' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), 'Result' => array( 'type' => 'integer', 'location' => 'xml',), 'SectionCount' => array( 'type' => 'integer', 'location' => 'xml',), 'PornInfo' => array( @@ -6778,24 +6580,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'TerrorismInfo' => array( @@ -6805,24 +6589,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'PoliticsInfo' => array( @@ -6832,24 +6598,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'AdsInfo' => array( @@ -6859,24 +6607,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'IllegalInfo' => array( @@ -6886,24 +6616,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), ), ), 'AbuseInfo' => array( @@ -6913,60 +6625,6 @@ class Service { 'HitFlag' => array( 'type' => 'integer', 'location' => 'xml',), 'Score' => array( 'type' => 'integer', 'location' => 'xml',), 'Keywords' => array( 'type' => 'string', 'location' => 'xml',), - 'SubLabel' => array( 'type' => 'string', 'location' => 'xml',), - 'LibResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'LibType' => array( 'type' => 'integer', 'location' => 'xml',), - 'LibName' => array( 'type' => 'string', 'location' => 'xml',), - 'Keywords' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - ), - ), - ), - ), - ), - ), - ), - 'UserInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'TokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Nickname' => array( 'type' => 'string', 'location' => 'xml',), - 'DeviceId' => array( 'type' => 'string', 'location' => 'xml',), - 'AppId' => array( 'type' => 'string', 'location' => 'xml',), - 'Room' => array( 'type' => 'string', 'location' => 'xml',), - 'IP' => array( 'type' => 'string', 'location' => 'xml',), - 'Type' => array( 'type' => 'string', 'location' => 'xml',), - 'ReceiveTokenId' => array( 'type' => 'string', 'location' => 'xml',), - 'Gender' => array( 'type' => 'string', 'location' => 'xml',), - 'Level' => array( 'type' => 'string', 'location' => 'xml',), - 'Role' => array( 'type' => 'string', 'location' => 'xml',), - ), - ), - 'ListInfo' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListResults' => array( - 'type' => 'array', - 'location' => 'xml', - 'items' => array( - 'type' => 'object', - 'location' => 'xml', - 'properties' => array( - 'ListType' => array( 'type' => 'integer', 'location' => 'xml',), - 'ListName' => array( 'type' => 'string', 'location' => 'xml',), - 'Entity' => array( 'type' => 'string', 'location' => 'xml',), ), ), ), @@ -7424,153 +7082,6 @@ class Service { 'CreateMediaVideoProcessJobsOutput' => Descriptions::CreateMediaVideoProcessJobsOutput(), 'CreateMediaVideoMontageJobsOutput' => Descriptions::CreateMediaVideoMontageJobsOutput(), 'CreateMediaAnimationJobsOutput' => Descriptions::CreateMediaAnimationJobsOutput(), - 'CreateMediaPicProcessJobsOutput' => Descriptions::CreateMediaPicProcessJobsOutput(), - 'CreateMediaSegmentJobsOutput' => Descriptions::CreateMediaSegmentJobsOutput(), - 'CreateMediaVideoTagJobsOutput' => Descriptions::CreateMediaVideoTagJobsOutput(), - 'CreateMediaSuperResolutionJobsOutput' => Descriptions::CreateMediaSuperResolutionJobsOutput(), - 'CreateMediaSDRtoHDRJobsOutput' => Descriptions::CreateMediaSDRtoHDRJobsOutput(), - 'CreateMediaDigitalWatermarkJobsOutput' => Descriptions::CreateMediaDigitalWatermarkJobsOutput(), - 'CreateMediaExtractDigitalWatermarkJobsOutput' => Descriptions::CreateMediaExtractDigitalWatermarkJobsOutput(), - 'DetectLiveVideoOutput' => Descriptions::DetectLiveVideoOutput(), - 'CancelLiveVideoAuditingOutput' => Descriptions::CancelLiveVideoAuditingOutput(), - 'OpticalOcrRecognitionOutput' => Descriptions::OpticalOcrRecognitionOutput(), - 'TriggerWorkflowOutput' => Descriptions::TriggerWorkflowOutput(), - 'GetWorkflowInstancesOutput' => Descriptions::GetWorkflowInstancesOutput(), - 'GetWorkflowInstanceOutput' => Descriptions::GetWorkflowInstanceOutput(), - 'CreateMediaSnapshotTemplateOutput' => Descriptions::CreateMediaSnapshotTemplateOutput(), - 'UpdateMediaSnapshotTemplateOutput' => Descriptions::UpdateMediaSnapshotTemplateOutput(), - 'CreateMediaTranscodeTemplateOutput' => Descriptions::CreateMediaTranscodeTemplateOutput(), - 'UpdateMediaTranscodeTemplateOutput' => Descriptions::UpdateMediaTranscodeTemplateOutput(), - 'CreateMediaHighSpeedHdTemplateOutput' => Descriptions::CreateMediaHighSpeedHdTemplateOutput(), - 'UpdateMediaHighSpeedHdTemplateOutput' => Descriptions::UpdateMediaHighSpeedHdTemplateOutput(), - 'CreateMediaAnimationTemplateOutput' => Descriptions::CreateMediaAnimationTemplateOutput(), - 'UpdateMediaAnimationTemplateOutput' => Descriptions::UpdateMediaAnimationTemplateOutput(), - 'CreateMediaConcatTemplateOutput' => Descriptions::CreateMediaConcatTemplateOutput(), - 'UpdateMediaConcatTemplateOutput' => Descriptions::UpdateMediaConcatTemplateOutput(), - 'CreateMediaVideoProcessTemplateOutput' => Descriptions::CreateMediaVideoProcessTemplateOutput(), - 'UpdateMediaVideoProcessTemplateOutput' => Descriptions::UpdateMediaVideoProcessTemplateOutput(), - 'CreateMediaVideoMontageTemplateOutput' => Descriptions::CreateMediaVideoMontageTemplateOutput(), - 'UpdateMediaVideoMontageTemplateOutput' => Descriptions::UpdateMediaVideoMontageTemplateOutput(), - 'CreateMediaVoiceSeparateTemplateOutput' => Descriptions::CreateMediaVoiceSeparateTemplateOutput(), - 'UpdateMediaVoiceSeparateTemplateOutput' => Descriptions::UpdateMediaVoiceSeparateTemplateOutput(), - 'CreateMediaSuperResolutionTemplateOutput' => Descriptions::CreateMediaSuperResolutionTemplateOutput(), - 'UpdateMediaSuperResolutionTemplateOutput' => Descriptions::UpdateMediaSuperResolutionTemplateOutput(), - 'CreateMediaPicProcessTemplateOutput' => Descriptions::CreateMediaPicProcessTemplateOutput(), - 'UpdateMediaPicProcessTemplateOutput' => Descriptions::UpdateMediaPicProcessTemplateOutput(), - 'CreateMediaWatermarkTemplateOutput' => Descriptions::CreateMediaWatermarkTemplateOutput(), - 'UpdateMediaWatermarkTemplateOutput' => Descriptions::UpdateMediaWatermarkTemplateOutput(), - 'DescribeMediaTemplatesOutput' => Descriptions::DescribeMediaTemplatesOutput(), - 'DescribeWorkflowOutput' => Descriptions::DescribeWorkflowOutput(), - 'DeleteWorkflowOutput' => Descriptions::DeleteWorkflowOutput(), - 'CreateInventoryTriggerJobOutput' => Descriptions::CreateInventoryTriggerJobOutput(), - 'DescribeInventoryTriggerJobsOutput' => Descriptions::DescribeInventoryTriggerJobsOutput(), - 'DescribeInventoryTriggerJobOutput' => Descriptions::DescribeInventoryTriggerJobOutput(), - 'CancelInventoryTriggerJobOutput' => Descriptions::CancelInventoryTriggerJobOutput(), - 'CreateMediaNoiseReductionJobsOutput' => Descriptions::CreateMediaNoiseReductionJobsOutput(), - 'ImageRepairProcessOutput' => Descriptions::ImageRepairProcessOutput(), - 'ImageDetectCarProcessOutput' => Descriptions::ImageDetectCarProcessOutput(), - 'ImageAssessQualityProcessOutput' => Descriptions::ImageAssessQualityProcessOutput(), - 'ImageSearchOpenOutput' => Descriptions::ImageSearchOpenOutput(), - 'ImageSearchAddOutput' => Descriptions::ImageSearchAddOutput(), - 'ImageSearchOutput' => Descriptions::ImageSearchOutput(), - 'ImageSearchDeleteOutput' => Descriptions::ImageSearchDeleteOutput(), - 'BindCiServiceOutput' => Descriptions::BindCiServiceOutput(), - 'GetCiServiceOutput' => Descriptions::GetCiServiceOutput(), - 'UnBindCiServiceOutput' => Descriptions::UnBindCiServiceOutput(), - 'GetHotLinkOutput' => Descriptions::GetHotLinkOutput(), - 'AddHotLinkOutput' => Descriptions::AddHotLinkOutput(), - 'OpenOriginProtectOutput' => Descriptions::OpenOriginProtectOutput(), - 'GetOriginProtectOutput' => Descriptions::GetOriginProtectOutput(), - 'CloseOriginProtectOutput' => Descriptions::CloseOriginProtectOutput(), - 'ImageDetectFaceOutput' => Descriptions::ImageDetectFaceOutput(), - 'ImageFaceEffectOutput' => Descriptions::ImageFaceEffectOutput(), - 'IDCardOCROutput' => Descriptions::IDCardOCROutput(), - 'IDCardOCRByUploadOutput' => Descriptions::IDCardOCRByUploadOutput(), - 'GetLiveCodeOutput' => Descriptions::GetLiveCodeOutput(), - 'GetActionSequenceOutput' => Descriptions::GetActionSequenceOutput(), - 'DescribeDocProcessBucketsOutput' => Descriptions::DescribeDocProcessBucketsOutput(), - 'UpdateDocProcessQueueOutput' => Descriptions::UpdateDocProcessQueueOutput(), - 'CreateMediaQualityEstimateJobsOutput' => Descriptions::CreateMediaQualityEstimateJobsOutput(), - 'CreateMediaStreamExtractJobsOutput' => Descriptions::CreateMediaStreamExtractJobsOutput(), - 'FileJobs4HashOutput' => Descriptions::FileJobs4HashOutput(), - 'OpenFileProcessServiceOutput' => Descriptions::OpenFileProcessServiceOutput(), - 'GetFileProcessQueueListOutput' => Descriptions::GetFileProcessQueueListOutput(), - 'UpdateFileProcessQueueOutput' => Descriptions::UpdateFileProcessQueueOutput(), - 'CreateFileHashCodeJobsOutput' => Descriptions::CreateFileHashCodeJobsOutput(), - 'GetFileHashCodeResultOutput' => Descriptions::GetFileHashCodeResultOutput(), - 'CreateFileUncompressJobsOutput' => Descriptions::CreateFileUncompressJobsOutput(), - 'GetFileUncompressResultOutput' => Descriptions::GetFileUncompressResultOutput(), - 'CreateFileCompressJobsOutput' => Descriptions::CreateFileCompressJobsOutput(), - 'GetFileCompressResultOutput' => Descriptions::GetFileCompressResultOutput(), - 'CreateM3U8PlayListJobsOutput' => Descriptions::CreateM3U8PlayListJobsOutput(), - 'GetPicQueueListOutput' => Descriptions::GetPicQueueListOutput(), - 'UpdatePicQueueOutput' => Descriptions::UpdatePicQueueOutput(), - 'GetPicBucketListOutput' => Descriptions::GetPicBucketListOutput(), - 'GetAiBucketListOutput' => Descriptions::GetAiBucketListOutput(), - 'OpenAiServiceOutput' => Descriptions::OpenAiServiceOutput(), - 'CloseAiServiceOutput' => Descriptions::CloseAiServiceOutput(), - 'GetAiQueueListOutput' => Descriptions::GetAiQueueListOutput(), - 'UpdateAiQueueOutput' => Descriptions::UpdateAiQueueOutput(), - 'CreateMediaTranscodeProTemplateOutput' => Descriptions::CreateMediaTranscodeProTemplateOutput(), - 'UpdateMediaTranscodeProTemplateOutput' => Descriptions::UpdateMediaTranscodeProTemplateOutput(), - 'CreateVoiceTtsTemplateOutput' => Descriptions::CreateVoiceTtsTemplateOutput(), - 'UpdateVoiceTtsTemplateOutput' => Descriptions::UpdateVoiceTtsTemplateOutput(), - 'CreateMediaSmartCoverTemplateOutput' => Descriptions::CreateMediaSmartCoverTemplateOutput(), - 'UpdateMediaSmartCoverTemplateOutput' => Descriptions::UpdateMediaSmartCoverTemplateOutput(), - 'CreateVoiceSpeechRecognitionTemplateOutput' => Descriptions::CreateVoiceSpeechRecognitionTemplateOutput(), - 'UpdateVoiceSpeechRecognitionTemplateOutput' => Descriptions::UpdateVoiceSpeechRecognitionTemplateOutput(), - 'CreateVoiceTtsJobsOutput' => Descriptions::CreateVoiceTtsJobsOutput(), - 'CreateAiTranslationJobsOutput' => Descriptions::CreateAiTranslationJobsOutput(), - 'CreateVoiceSpeechRecognitionJobsOutput' => Descriptions::CreateVoiceSpeechRecognitionJobsOutput(), - 'CreateAiWordsGeneralizeJobsOutput' => Descriptions::CreateAiWordsGeneralizeJobsOutput(), - 'CreateMediaVideoEnhanceJobsOutput' => Descriptions::CreateMediaVideoEnhanceJobsOutput(), - 'CreateMediaVideoEnhanceTemplateOutput' => Descriptions::CreateMediaVideoEnhanceTemplateOutput(), - 'UpdateMediaVideoEnhanceTemplateOutput' => Descriptions::UpdateMediaVideoEnhanceTemplateOutput(), - 'OpenImageSlimOutput' => Descriptions::OpenImageSlimOutput(), - 'CloseImageSlimOutput' => Descriptions::CloseImageSlimOutput(), - 'GetImageSlimOutput' => Descriptions::GetImageSlimOutput(), - 'AutoTranslationBlockProcessOutput' => Descriptions::AutoTranslationBlockProcessOutput(), - 'RecognizeLogoProcessOutput' => Descriptions::RecognizeLogoProcessOutput(), - 'DetectLabelProcessOutput' => Descriptions::DetectLabelProcessOutput(), - 'AIGameRecProcessOutput' => Descriptions::AIGameRecProcessOutput(), - 'AIBodyRecognitionProcessOutput' => Descriptions::AIBodyRecognitionProcessOutput(), - 'DetectPetProcessOutput' => Descriptions::DetectPetProcessOutput(), - 'AILicenseRecProcessOutput' => Descriptions::AILicenseRecProcessOutput(), - 'CreateMediaTargetRecTemplateOutput' => Descriptions::CreateMediaTargetRecTemplateOutput(), - 'UpdateMediaTargetRecTemplateOutput' => Descriptions::UpdateMediaTargetRecTemplateOutput(), - 'CreateMediaTargetRecJobsOutput' => Descriptions::CreateMediaTargetRecJobsOutput(), - 'CreateMediaSegmentVideoBodyJobsOutput' => Descriptions::CreateMediaSegmentVideoBodyJobsOutput(), - 'OpenAsrServiceOutput' => Descriptions::OpenAsrServiceOutput(), - 'GetAsrBucketListOutput' => Descriptions::GetAsrBucketListOutput(), - 'CloseAsrServiceOutput' => Descriptions::CloseAsrServiceOutput(), - 'GetAsrQueueListOutput' => Descriptions::GetAsrQueueListOutput(), - 'UpdateAsrQueueOutput' => Descriptions::UpdateAsrQueueOutput(), - 'CreateMediaNoiseReductionTemplateOutput' => Descriptions::CreateMediaNoiseReductionTemplateOutput(), - 'UpdateMediaNoiseReductionTemplateOutput' => Descriptions::UpdateMediaNoiseReductionTemplateOutput(), - 'CreateVoiceSoundHoundJobsOutput' => Descriptions::CreateVoiceSoundHoundJobsOutput(), - 'CreateVoiceVocalScoreJobsOutput' => Descriptions::CreateVoiceVocalScoreJobsOutput(), - 'CreateDatasetOutput' => Descriptions::CreateDatasetOutput(), - 'CreateDatasetBindingOutput' => Descriptions::CreateDatasetBindingOutput(), - 'CreateFileMetaIndexOutput' => Descriptions::CreateFileMetaIndexOutput(), - 'DatasetFaceSearchOutput' => Descriptions::DatasetFaceSearchOutput(), - 'DatasetSimpleQueryOutput' => Descriptions::DatasetSimpleQueryOutput(), - 'DeleteDatasetOutput' => Descriptions::DeleteDatasetOutput(), - 'DeleteDatasetBindingOutput' => Descriptions::DeleteDatasetBindingOutput(), - 'DeleteFileMetaIndexOutput' => Descriptions::DeleteFileMetaIndexOutput(), - 'DescribeDatasetOutput' => Descriptions::DescribeDatasetOutput(), - 'DescribeDatasetBindingOutput' => Descriptions::DescribeDatasetBindingOutput(), - 'DescribeDatasetBindingsOutput' => Descriptions::DescribeDatasetBindingsOutput(), - 'DescribeDatasetsOutput' => Descriptions::DescribeDatasetsOutput(), - 'DescribeFileMetaIndexOutput' => Descriptions::DescribeFileMetaIndexOutput(), - 'SearchImageOutput' => Descriptions::SearchImageOutput(), - 'UpdateDatasetOutput' => Descriptions::UpdateDatasetOutput(), - 'UpdateFileMetaIndexOutput' => Descriptions::UpdateFileMetaIndexOutput(), - 'ZipFilePreviewOutput' => Descriptions::ZipFilePreviewOutput(), - 'GetHLSPlayKeyOutput' => Descriptions::GetHLSPlayKeyOutput(), - 'PostWatermarkJobsOutput' => Descriptions::PostWatermarkJobsOutput(), - 'GeneratePlayListOutput' => Descriptions::GeneratePlayListOutput(), - 'CreateWatermarkTemplateOutput' => Descriptions::CreateWatermarkTemplateOutput(), - ) ); } diff --git a/src/vendor/qcloud/cos-sdk-v5/src/Signature.php b/src/vendor/qcloud/cos-sdk-v5/src/Signature.php index c01ac9014..28e03d94a 100644 --- a/src/vendor/qcloud/cos-sdk-v5/src/Signature.php +++ b/src/vendor/qcloud/cos-sdk-v5/src/Signature.php @@ -14,12 +14,6 @@ class Signature { // array: cos config. private $options; - // string: token. - private $token; - - // array: sign header. - private $signHeader; - public function __construct( $accessKey, $secretKey, $options, $token = null ) { $this->accessKey = $accessKey; $this->secretKey = $secretKey; @@ -32,6 +26,7 @@ class Signature { 'content-length', 'content-md5', 'content-type', + 'expect', 'expires', 'host', 'if-match', @@ -40,10 +35,16 @@ class Signature { 'if-unmodified-since', 'origin', 'range', + 'response-cache-control', + 'response-content-disposition', + 'response-content-encoding', + 'response-content-language', + 'response-content-type', + 'response-expires', 'transfer-encoding', - 'pic-operations', + 'versionid', ]; - date_default_timezone_set($this->options['timezone']); + date_default_timezone_set( 'PRC' ); } public function __destruct() { @@ -53,9 +54,6 @@ class Signature { if ( startWith( $header, 'x-cos-' ) ) { return true; } - if ( startWith( $header, 'x-ci-' ) ) { - return true; - } if ( in_array( $header, $this->signHeader ) ) { return true; } diff --git a/src/vendor/qiniu/php-sdk/.github/workflows/test-ci.yml b/src/vendor/qiniu/php-sdk/.github/workflows/test-ci.yml index 00f964e40..a3f76f19e 100644 --- a/src/vendor/qiniu/php-sdk/.github/workflows/test-ci.yml +++ b/src/vendor/qiniu/php-sdk/.github/workflows/test-ci.yml @@ -1,37 +1,22 @@ name: PHP CI with Composer -on: [push, pull_request] +on: + push: + paths-ignore: + - '**.md' jobs: build: strategy: fail-fast: false + max-parallel: 1 matrix: - php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php-versions: ['5.4', '5.5', '5.6', '7.0'] runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - - name: Setup php for mock server - uses: shivammathur/setup-php@v2 - with: - php-version: '8.2' - - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: '1.21.x' - - - name: Setup build-in server - run: | - nohup php -S localhost:9000 -t ./tests/mock-server/ > phpd.log 2>&1 & - echo $! > mock-server.pid - - cd tests/socks5-server/ - nohup go run main.go > ../../socks5.log 2>&1 & - echo $! > ../../socks-server.pid - - name: Setup php uses: shivammathur/setup-php@v2 with: @@ -48,8 +33,6 @@ jobs: ./vendor/bin/phpcs --standard=PSR2 examples ./vendor/bin/phpcs --standard=PSR2 tests ./vendor/bin/phpunit --coverage-clover=coverage.xml - cat mock-server.pid | xargs kill - cat socks-server.pid | xargs kill env: QINIU_ACCESS_KEY: ${{ secrets.QINIU_ACCESS_KEY }} @@ -57,15 +40,5 @@ jobs: QINIU_TEST_BUCKET: ${{ secrets.QINIU_TEST_BUCKET }} QINIU_TEST_DOMAIN: ${{ secrets.QINIU_TEST_DOMAIN }} - - name: Print mock server log - if: ${{ failure() }} - run: | - cat phpd.log - - - name: Print socks5 server log - if: ${{ failure() }} - run: | - cat socks5.log - - name: After_success run: bash <(curl -s https://codecov.io/bash) diff --git a/src/vendor/qiniu/php-sdk/CHANGELOG.md b/src/vendor/qiniu/php-sdk/CHANGELOG.md index 6f8da5d85..200b76a8e 100644 --- a/src/vendor/qiniu/php-sdk/CHANGELOG.md +++ b/src/vendor/qiniu/php-sdk/CHANGELOG.md @@ -1,54 +1,5 @@ # Changelog -## 7.14.0 (2024-10-16) -* 对象存储,持久化处理支持工作流模版 - -## 7.13.0 (2024-09-05) -* 对象存储,验证回调方法新增支持 Qiniu 签名 -* 对象存储,调整查询空间区域域名顺序与默认空间管理域名 -* 支持闲时任务配置 - -## 7.12.1 (2024-02-21) -* 对象存储,添加上传策略部分字段 - -## 7.12.0 (2023-12-11) -* 对象存储,支持归档直读存储 -* 对象存储,批量操作支持自动查询 rs 服务域名 - -## 7.11.0 (2023-09-05) -* 支持代理 - -## 7.10.1 (2023-08-04) -* 修复部分 API 调用中间件合并失败(#417) - -## 7.10.0 (2023-06-20) -* 对象存储,新增请求中间件逻辑,方便拓展请求逻辑 -* 对象存储,新增备用 UC 域名用于查询区域域名 -* 对象存储,修复分片上传初始化失败无法快速失败 -* 对象存储,移除首尔区域 - -## 7.9.0 (2023-03-31) -* 对象存储,修复无法对 key 为空字符串的对象进行操作 -* 修复 301 重定向无法正确获取 header 信息 -* 对象存储,新增查询区域域名过期时间 -* 对象存储,更新获取区域域名的接口 -* 对象存储,更新查询 bucket 域名为 uc 服务 -* 对象存储,新增 uc 服务可配置 - -## 7.8.0 (2022-10-25) -* 移除不推荐域名,并增加区域亚太-首尔和华东-浙江2 -* 对象存储,修复断点上传的文件内容不正确 -* 对象存储,优化分片上传 ctx 超时检测 - -## 7.7.0 (2022-09-02) -* 对象存储,新增支持设置文件级别生命周期 setObjectLifecycle API -* 对象存储,内置增加七牛新建存储区域域名信息 -* 修复当前已知问题 - -## 7.6.0 (2022-06-08) -* 对象存储,管理类 API 发送请求时增加 [X-Qiniu-Date](https://developer.qiniu.com/kodo/3924/common-request-headers) (生成请求的时间) header - - ## 7.5.0 (2022-04-18) * 对象存储,新增支持 [深度归档存储类型](https://developer.qiniu.com/kodo/3956/kodo-category#deep_archive) @@ -68,10 +19,10 @@ ### 新增 * 【对象存储】增加异步抓取方法与demo * 【融合cdn】增加查询CDN刷新记录、查询CDN预取记录方法与demo -* 【云短信】增加查询短信发送记录的方法 +* 【云短信】增加查询短信发送记录的方法 * 【实时音视频】增加rtc停止房间的合流转推方法 * 【内容审核】增加图片审核、视频审核方法与demo - + ### 修复 * 【对象存储】修复签算 token 时上传策略中的 forceSaveKey 字段不生效的问题 * 【对象存储】修复更新空间事件通知规则方法 @@ -118,7 +69,7 @@ ## 7.1.4 (2017-06-21) ### 增加 * cdn 文件/目录 刷新 -* cdn 获取 流量/带宽 +* cdn 获取 流量/带宽 * cdn 获取域名的访问日志列表 * cdn 对资源链接进行时间戳防盗链签名 diff --git a/src/vendor/qiniu/php-sdk/README.md b/src/vendor/qiniu/php-sdk/README.md index 784d735a4..447a07d9f 100644 --- a/src/vendor/qiniu/php-sdk/README.md +++ b/src/vendor/qiniu/php-sdk/README.md @@ -12,18 +12,18 @@ ## 安装 -推荐使用 `composer` 进行安装。可以使用 composer.json 声明依赖,或者运行下面的命令。SDK 包已经放到这里 [`qiniu/php-sdk`][install-packagist] 。 - +* 推荐使用 `composer` 进行安装。可以使用 composer.json 声明依赖,或者运行下面的命令。SDK 包已经放到这里 [`qiniu/php-sdk`][install-packagist] 。 ```bash $ composer require qiniu/php-sdk ``` +* 直接下载安装,SDK 没有依赖其他第三方库,但需要参照 composer 的 autoloader,增加一个自己的 autoloader 程序。 ## 运行环境 -| Qiniu SDK版本 | PHP 版本 | -|:--------------------:|:-----------------------------------------------:| -| 7.x | cURL extension, 5.3 - 5.6, 7.0 - 7.4, 8.0-8.1 | -| 6.x | cURL extension, 5.2 - 5.6 | +| Qiniu SDK版本 | PHP 版本 | +|:--------------------:|:---------------------------:| +| 7.x | cURL extension, 5.3 - 5.6,7.0 | +| 6.x | cURL extension, 5.2 - 5.6 | ## 使用方法 diff --git a/src/vendor/qiniu/php-sdk/autoload.php b/src/vendor/qiniu/php-sdk/autoload.php index 9efddd78a..b553d1c02 100644 --- a/src/vendor/qiniu/php-sdk/autoload.php +++ b/src/vendor/qiniu/php-sdk/autoload.php @@ -16,4 +16,3 @@ function classLoader($class) spl_autoload_register('classLoader'); require_once __DIR__ . '/src/Qiniu/functions.php'; -require_once __DIR__ . '/src/Qiniu/Http/Middleware/Middleware.php'; diff --git a/src/vendor/qiniu/php-sdk/composer.json b/src/vendor/qiniu/php-sdk/composer.json index a2859f209..bf5c72523 100644 --- a/src/vendor/qiniu/php-sdk/composer.json +++ b/src/vendor/qiniu/php-sdk/composer.json @@ -19,22 +19,19 @@ ], "require": { "php": ">=5.3.3", - "ext-xml": "*", - "ext-curl": "*", - "myclabs/php-enum": "~1.5.2 || ~1.6.6 || ~1.7.7 || ~1.8.4" + "myclabs/php-enum": "1.6.6" }, "require-dev": { "paragonie/random_compat": ">=2", - "phpunit/phpunit": "^4.8 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4", - "squizlabs/php_codesniffer": "^2.3 || ~3.6" + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~3.6" }, "autoload": { "psr-4": { "Qiniu\\": "src/Qiniu" }, "files": [ - "src/Qiniu/functions.php", - "src/Qiniu/Http/Middleware/Middleware.php" + "src/Qiniu/functions.php" ] } } diff --git a/src/vendor/qiniu/php-sdk/examples/bucket_lifecycleRule.php b/src/vendor/qiniu/php-sdk/examples/bucket_lifecycleRule.php index f51524cd3..9dc0f84c2 100644 --- a/src/vendor/qiniu/php-sdk/examples/bucket_lifecycleRule.php +++ b/src/vendor/qiniu/php-sdk/examples/bucket_lifecycleRule.php @@ -21,7 +21,6 @@ $name = 'demo'; // 生命周期规则名称 $prefix = 'test'; // 规则策略中的前缀 $delete_after_days = 80; // 用户新创建的文件将在该设定时间之后自动删除 $to_line_after_days = 70; // 用户新创建的文件将在该设定的时间之后自动转为低频存储 -$to_archive_ir_after_days = 71; // 用户新创建的文件将在该设定的时间之后自动转为归档直读存储 $to_archive_after_days = 72; // 用户新创建的文件将在该设定的时间之后自动转为归档存储 $to_deep_archive_after_days = 74; // 用户新创建的文件将在该设定的时间之后自动转为深度归档存储 @@ -32,8 +31,7 @@ list($ret, $err) = $bucketManager->bucketLifecycleRule( $delete_after_days, $to_line_after_days, $to_archive_after_days, - $to_deep_archive_after_days, - $to_archive_ir_after_days + $to_deep_archive_after_days ); if ($err != null) { var_dump($err); diff --git a/src/vendor/qiniu/php-sdk/examples/rs_batch_change_type.php b/src/vendor/qiniu/php-sdk/examples/rs_batch_change_type.php index a19d0d47b..6c8df84a1 100644 --- a/src/vendor/qiniu/php-sdk/examples/rs_batch_change_type.php +++ b/src/vendor/qiniu/php-sdk/examples/rs_batch_change_type.php @@ -31,7 +31,6 @@ $keyTypePairs = array(); // 1 表示低频存储 // 2 表示归档存储 // 3 表示深度归档存储 -// 4 表示归档直读存储 foreach ($keys as $key) { $keyTypePairs[$key] = 1; } diff --git a/src/vendor/qiniu/php-sdk/examples/rs_change_type.php b/src/vendor/qiniu/php-sdk/examples/rs_change_type.php index 8b3201fcd..802c9f446 100644 --- a/src/vendor/qiniu/php-sdk/examples/rs_change_type.php +++ b/src/vendor/qiniu/php-sdk/examples/rs_change_type.php @@ -21,12 +21,7 @@ $bucketManager = new BucketManager($auth, $config); // 参考文档:https://developer.qiniu.com/kodo/api/3710/chtype $key = "qiniu.mp4"; -// 0 表示标准存储; -// 1 表示低频存储; -// 2 表示归档存储; -// 3 表示深度归档存储; -// 4 表示归档直读存储; -$fileType = 1; +$fileType = 1; // 0 表示标准存储;1 表示低频存储;2 表示归档存储;3 表示深度归档存储 list($ret, $err) = $bucketManager->changeType($bucket, $key, $fileType); if ($err != null) { diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Auth.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Auth.php index 6da2be4e6..22cd3953e 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Auth.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Auth.php @@ -1,5 +1,4 @@ accessKey = $accessKey; $this->secretKey = $secretKey; - $defaultOptions = array( - 'disableQiniuTimestampSignature' => null - ); - if ($options == null) { - $options = $defaultOptions; - } - $this->options = array_merge($defaultOptions, $options); } public function getAccessKey() @@ -95,7 +86,7 @@ final class Auth $data .= ":" . $url["port"]; } - // try to append content type + // try append content type if ($headers != null && isset($headers["Content-Type"])) { // append content type $data .= "\n"; @@ -123,43 +114,19 @@ final class Auth // append body $data .= "\n\n"; - if (!is_null($body) - && strlen($body) > 0 + if (strlen($body) > 0 && isset($headers["Content-Type"]) && $headers["Content-Type"] != "application/octet-stream" ) { $data .= $body; } - return array($this->sign($data), null); + return array($this->sign(utf8_encode($data)), null); } - public function verifyCallback( - $contentType, - $originAuthorization, - $url, - $body, - $method = "GET", - $headers = array() - ) { - if (strpos($originAuthorization, 'Qiniu') === 0) { - $qnHeaders = new Header($headers); - if (!isset($qnHeaders['Content-Type'])) { - $qnHeaders['Content-Type'] = $contentType; - } - list($sign, $err) = $this->signQiniuAuthorization( - $url, - $method, - $body, - $qnHeaders - ); - if ($err !== null) { - return false; - } - $authorization = 'Qiniu ' . $sign; - } else { - $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); - } + public function verifyCallback($contentType, $originAuthorization, $url, $body) + { + $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); return $originAuthorization === $authorization; } @@ -219,19 +186,13 @@ final class Auth 'fsizeMin', 'fsizeLimit', - 'persistentOps', // 与 persistentWorkflowTemplateID 二选一 + 'persistentOps', 'persistentNotifyUrl', 'persistentPipeline', - 'persistentType', // 为 `1` 时开启闲时任务 - 'persistentWorkflowTemplateID', // 与 persistentOps 二选一 'deleteAfterDays', 'fileType', 'isPrefixalScope', - - 'transform', // deprecated - 'transformFallbackKey', // deprecated - 'transformFallbackMode', // deprecated ); private static function copyPolicy(&$policy, $originPolicy, $strictPolicy) @@ -255,29 +216,14 @@ final class Auth public function authorizationV2($url, $method, $body = null, $contentType = null) { - $headers = new Header(); + $headers = null; $result = array(); if ($contentType != null) { - $headers['Content-Type'] = $contentType; + $headers = new Header(array( + 'Content-Type' => array($contentType), + )); $result['Content-Type'] = $contentType; } - - $signDate = gmdate('Ymd\THis\Z', time()); - if ($this->options['disableQiniuTimestampSignature'] !== null) { - if (!$this->options['disableQiniuTimestampSignature']) { - $headers['X-Qiniu-Date'] = $signDate; - $result['X-Qiniu-Date'] = $signDate; - } - } elseif (getenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE")) { - if (strtolower(getenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE")) !== "true") { - $headers['X-Qiniu-Date'] = $signDate; - $result['X-Qiniu-Date'] = $signDate; - } - } else { - $headers['X-Qiniu-Date'] = $signDate; - $result['X-Qiniu-Date'] = $signDate; - } - list($sign) = $this->signQiniuAuthorization($url, $method, $body, $headers); $result['Authorization'] = 'Qiniu ' . $sign; return $result; diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Cdn/CdnManager.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Cdn/CdnManager.php index 60052d3e2..a6efcedb3 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Cdn/CdnManager.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Cdn/CdnManager.php @@ -5,20 +5,17 @@ namespace Qiniu\Cdn; use Qiniu\Auth; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\Proxy; final class CdnManager { private $auth; private $server; - private $proxy; - public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) + public function __construct(Auth $auth) { $this->auth = $auth; $this->server = 'http://fusion.qiniuapi.com'; - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -228,7 +225,7 @@ final class CdnManager { $headers = $this->auth->authorization($url, $body, 'application/json'); $headers['Content-Type'] = 'application/json'; - $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); + $ret = Client::post($url, $body, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Config.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Config.php index 3ce7fa5a5..b93d99c59 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Config.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Config.php @@ -1,24 +1,22 @@ useHTTPS = false; $this->useCdnDomains = false; $this->regionCache = array(); - $this->ucHost = Config::UC_HOST; - $this->queryRegionHost = Config::QUERY_REGION_HOST; - $this->backupQueryRegionHosts = array( - "kodo-config.qiniuapi.com", - "uc.qbox.me", - ); - $this->backupUcHostsRetryTimes = 2; } - public function setUcHost($ucHost) + public function getUpHost($accessKey, $bucket) { - $this->ucHost = $ucHost; - $this->setQueryRegionHost($ucHost); - } - - public function getUcHost() - { - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return $scheme . $this->ucHost; - } - - public function setQueryRegionHost($host, $backupHosts = array()) - { - $this->queryRegionHost = $host; - $this->backupQueryRegionHosts = $backupHosts; - } - - public function getQueryRegionHost() - { - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return $scheme . $this->queryRegionHost; - } - - public function setBackupQueryRegionHosts($hosts = array()) - { - $this->backupQueryRegionHosts = $hosts; - } - - public function getBackupQueryRegionHosts() - { - return $this->backupQueryRegionHosts; - } - - public function getUpHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; } else { @@ -117,30 +53,9 @@ final class Config return $scheme . $host; } - public function getUpHostV2($accessKey, $bucket, $reqOpt = null) + public function getUpBackupHost($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - $host = $region->srcUpHosts[0]; - if ($this->useCdnDomains === true) { - $host = $region->cdnUpHosts[0]; - } - - return array($scheme . $host, null); - } - - public function getUpBackupHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; } else { @@ -155,30 +70,9 @@ final class Config return $scheme . $host; } - public function getUpBackupHostV2($accessKey, $bucket, $reqOpt = null) + public function getRsHost($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - $host = $region->cdnUpHosts[0]; - if ($this->useCdnDomains === true) { - $host = $region->srcUpHosts[0]; - } - - return array($scheme . $host, null); - } - - public function getRsHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -189,25 +83,9 @@ final class Config return $scheme . $region->rsHost; } - public function getRsHostV2($accessKey, $bucket, $reqOpt = null) + public function getRsfHost($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return array($scheme . $region->rsHost, null); - } - - public function getRsfHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -218,25 +96,9 @@ final class Config return $scheme . $region->rsfHost; } - public function getRsfHostV2($accessKey, $bucket, $reqOpt = null) + public function getIovipHost($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return array($scheme . $region->rsfHost, null); - } - - public function getIovipHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -247,25 +109,9 @@ final class Config return $scheme . $region->iovipHost; } - public function getIovipHostV2($accessKey, $bucket, $reqOpt = null) + public function getApiHost($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return array($scheme . $region->iovipHost, null); - } - - public function getApiHost($accessKey, $bucket, $reqOpt = null) - { - $region = $this->getRegion($accessKey, $bucket, $reqOpt); + $region = $this->getRegion($accessKey, $bucket); if ($this->useHTTPS === true) { $scheme = "https://"; @@ -276,123 +122,25 @@ final class Config return $scheme . $region->apiHost; } - public function getApiHostV2($accessKey, $bucket, $reqOpt = null) + private function getRegion($accessKey, $bucket) { - list($region, $err) = $this->getRegionV2($accessKey, $bucket, $reqOpt); - if ($err != null) { - return array(null, $err); - } - - if ($this->useHTTPS === true) { - $scheme = "https://"; - } else { - $scheme = "http://"; - } - - return array($scheme . $region->apiHost, null); - } - - - /** - * 从缓存中获取区域 - * - * @param string $cacheId 缓存 ID - * @return null|Region - */ - private function getRegionCache($cacheId) - { - if (isset($this->regionCache[$cacheId]) && - isset($this->regionCache[$cacheId]["deadline"]) && - time() < $this->regionCache[$cacheId]["deadline"]) { - return $this->regionCache[$cacheId]["region"]; - } - - return null; - } - - /** - * 将区域设置到缓存中 - * - * @param string $cacheId 缓存 ID - * @param Region $region 缓存 ID - * @return void - */ - private function setRegionCache($cacheId, $region) - { - $this->regionCache[$cacheId] = array( - "region" => $region, - ); - if (isset($region->ttl)) { - $this->regionCache[$cacheId]["deadline"] = time() + $region->ttl; - } - } - - /** - * 从缓存中获取区域 - * - * @param string $accessKey - * @param string $bucket - * @return Region - * - * @throws \Exception - */ - private function getRegion($accessKey, $bucket, $reqOpt = null) - { - if (isset($this->zone)) { - return $this->zone; - } - $cacheId = "$accessKey:$bucket"; - $regionCache = $this->getRegionCache($cacheId); - if ($regionCache) { - return $regionCache; - } - $region = Zone::queryZone( - $accessKey, - $bucket, - $this->getQueryRegionHost(), - $this->getBackupQueryRegionHosts(), - $this->backupUcHostsRetryTimes, - $reqOpt - ); - if (is_array($region)) { - list($region, $err) = $region; - if ($err != null) { - throw new \Exception($err->message()); + if (isset($this->regionCache[$cacheId])) { + $region = $this->regionCache[$cacheId]; + } elseif (isset($this->zone)) { + $region = $this->zone; + $this->regionCache[$cacheId] = $region; + } else { + $region = Zone::queryZone($accessKey, $bucket); + if (is_array($region)) { + list($region, $err) = $region; + if ($err != null) { + throw new \Exception($err->message()); + } } + $this->regionCache[$cacheId] = $region; } - - $this->setRegionCache($cacheId, $region); return $region; } - - private function getRegionV2($accessKey, $bucket, $reqOpt = null) - { - if (isset($this->zone)) { - return array($this->zone, null); - } - - $cacheId = "$accessKey:$bucket"; - $regionCache = $this->getRegionCache($cacheId); - if (isset($regionCache)) { - return array($regionCache, null); - } - - $region = Zone::queryZone( - $accessKey, - $bucket, - $this->getQueryRegionHost(), - $this->getBackupQueryRegionHosts(), - $this->backupUcHostsRetryTimes, - $reqOpt - ); - if (is_array($region)) { - list($region, $err) = $region; - return array($region, $err); - } - - $this->setRegionCache($cacheId, $region); - return array($region, null); - } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Enum/QiniuEnum.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Enum/QiniuEnum.php index 8399b5420..28afac875 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Enum/QiniuEnum.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Enum/QiniuEnum.php @@ -1,53 +1,41 @@ opt->middlewares; - $handle = Middleware\compose($middlewares, function ($req) { - return Client::sendRequest($req); - }); - return $handle($request); - } - - /** - * @param Request $request - * @return Response - */ public static function sendRequest($request) { $t1 = microtime(true); @@ -145,14 +91,13 @@ final class Client $options = array( CURLOPT_USERAGENT => self::userAgent(), CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false, CURLOPT_HEADER => true, CURLOPT_NOBODY => false, CURLOPT_CUSTOMREQUEST => $request->method, CURLOPT_URL => $request->url, ); - foreach ($request->opt->getCurlOpt() as $k => $v) { - $options[$k] = $v; - } // Handle open_basedir & safe mode if (!ini_get('safe_mode') && !ini_get('open_basedir')) { $options[CURLOPT_FOLLOWLOCATION] = true; @@ -188,9 +133,6 @@ final class Client private static function escapeQuotes($str) { - if (is_null($str)) { - return null; - } $find = array("\\", "\""); $replace = array("\\\\", "\\\""); return str_replace($find, $replace, $str); diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Error.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Error.php index 8fba74f1a..73477cf40 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Error.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Error.php @@ -10,9 +10,6 @@ namespace Qiniu\Http; final class Error { private $url; - /** - * @var Response - */ private $response; public function __construct($url, $response) diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Header.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Header.php index 1dcf328ea..cac8d824e 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Header.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Header.php @@ -8,7 +8,7 @@ namespace Qiniu\Http; class Header implements \ArrayAccess, \IteratorAggregate, \Countable { /** @var array normalized key name map */ - private $data = array(); + private $data; /** * @param array $obj non-normalized header object @@ -18,18 +18,8 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable foreach ($obj as $key => $values) { $normalizedKey = self::normalizeKey($key); $normalizedValues = array(); - if (!is_array($values)) { - array_push( - $normalizedValues, - self::normalizeValue($values) - ); - } else { - foreach ($values as $value) { - array_push( - $normalizedValues, - self::normalizeValue($value) - ); - } + foreach ($values as $value) { + array_push($normalizedValues, self::normalizeValue($value)); } $this->data[$normalizedKey] = $normalizedValues; } @@ -45,9 +35,8 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable */ public static function parseRawText($raw) { - $multipleHeaders = explode("\r\n\r\n", trim($raw)); $headers = array(); - $headerLines = explode("\r\n", end($multipleHeaders)); + $headerLines = explode("\r\n", $raw); foreach ($headerLines as $line) { $headerLine = trim($line); $kv = explode(':', $headerLine); @@ -93,7 +82,7 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable return $key; } - return \Qiniu\ucwords(strtolower($key), '-'); + return ucwords(strtolower($key), '-'); } /** @@ -122,7 +111,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable * * @return boolean */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function offsetExists($offset) { $key = self::normalizeKey($offset); @@ -134,7 +122,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable * * @return string|null */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function offsetGet($offset) { $key = self::normalizeKey($offset); @@ -151,7 +138,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable * * @return void */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function offsetSet($offset, $value) { $key = self::normalizeKey($offset); @@ -165,7 +151,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable /** * @return void */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function offsetUnset($offset) { $key = self::normalizeKey($offset); @@ -175,7 +160,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable /** * @return \ArrayIterator */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function getIterator() { $arr = array(); @@ -188,7 +172,6 @@ class Header implements \ArrayAccess, \IteratorAggregate, \Countable /** * @return int */ - #[\ReturnTypeWillChange] // temporarily suppress the type check of php 8.x public function count() { return count($this->data); diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Request.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Request.php index 5a31bf6c8..43b0bfdb2 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Request.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Request.php @@ -3,40 +3,16 @@ namespace Qiniu\Http; final class Request { - /** - * @var string - */ public $url; - - /** - * @var array - */ public $headers; - - /** - * @var mixed|null - */ public $body; - - /** - * @var string - */ public $method; - /** - * @var RequestOptions - */ - public $opt; - - public function __construct($method, $url, array $headers = array(), $body = null, $opt = null) + public function __construct($method, $url, array $headers = array(), $body = null) { $this->method = strtoupper($method); $this->url = $url; $this->headers = $headers; $this->body = $body; - if ($opt === null) { - $opt = new RequestOptions(); - } - $this->opt = $opt; } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Response.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Response.php index cd77903f2..bb50dd9aa 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Response.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Http/Response.php @@ -199,18 +199,10 @@ final class Response public function needRetry() { - if ($this->statusCode > 0 && $this->statusCode < 500) { - return false; + $code = $this->statusCode; + if ($code < 0 || ($code / 100 === 5 and $code !== 579) || $code === 996) { + return true; } - - // https://developer.qiniu.com/fusion/kb/1352/the-http-request-return-a-status-code - if (in_array($this->statusCode, array( - 501, 509, 573, 579, 608, 612, 614, 616, 618, 630, 631, 632, 640, 701 - ))) { - return false; - } - - return true; } private static function isJson($headers) diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/Operation.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/Operation.php index 839703c04..7cdd352b6 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/Operation.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/Operation.php @@ -4,7 +4,6 @@ namespace Qiniu\Processing; use Qiniu\Http\Client; use Qiniu\Http\Error; -use Qiniu\Http\Proxy; final class Operation { @@ -12,20 +11,12 @@ final class Operation private $auth; private $token_expire; private $domain; - private $proxy; - public function __construct( - $domain, - $auth = null, - $token_expire = 3600, - $proxy = null, - $proxy_auth = null, - $proxy_user_password = null - ) { + public function __construct($domain, $auth = null, $token_expire = 3600) + { $this->auth = $auth; $this->domain = $domain; $this->token_expire = $token_expire; - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } @@ -43,7 +34,7 @@ final class Operation public function execute($key, $fops) { $url = $this->buildUrl($key, $fops); - $resp = Client::get($url, array(), $this->proxy->makeReqOpt()); + $resp = Client::get($url); if (!$resp->ok()) { return array(null, new Error($url, $resp)); } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/PersistentFop.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/PersistentFop.php index 8dca4a9f2..ac95d251e 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/PersistentFop.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Processing/PersistentFop.php @@ -5,8 +5,6 @@ namespace Qiniu\Processing; use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\Proxy; -use Qiniu\Zone; /** * 持久化处理类,该类用于主动触发异步持久化操作. @@ -25,13 +23,8 @@ final class PersistentFop * */ private $config; - /** - * @var 代理信息 - */ - private $proxy; - - public function __construct($auth, $config = null, $proxy = null, $proxy_auth = null, $proxy_user_password = null) + public function __construct($auth, $config = null) { $this->auth = $auth; if ($config == null) { @@ -39,49 +32,31 @@ final class PersistentFop } else { $this->config = $config; } - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** * 对资源文件进行异步持久化处理 * @param string $bucket 资源所在空间 * @param string $key 待处理的源文件 - * @param string|array $fops 待处理的pfop操作,多个pfop操作以array的形式传入。 + * @param string $fops string|array 待处理的pfop操作,多个pfop操作以array的形式传入。 * eg. avthumb/mp3/ab/192k, vframe/jpg/offset/7/w/480/h/360 * @param string $pipeline 资源处理队列 * @param string $notify_url 处理结果通知地址 * @param bool $force 是否强制执行一次新的指令 - * @param int $type 为 `1` 时开启闲时任务 * * - * @return array 返回持久化处理的 persistentId 与可能出现的错误。 + * @return array 返回持久化处理的persistentId, 和返回的错误。 * * @link http://developer.qiniu.com/docs/v6/api/reference/fop/ */ - public function execute( - $bucket, - $key, - $fops = null, - $pipeline = null, - $notify_url = null, - $force = false, - $type = null, - $workflow_template_id = null - ) { + public function execute($bucket, $key, $fops, $pipeline = null, $notify_url = null, $force = false) + { if (is_array($fops)) { $fops = implode(';', $fops); } - - if (!$fops && !$workflow_template_id) { - throw new \InvalidArgumentException('Must provide one of fops or template_id'); - } - - $params = array('bucket' => $bucket, 'key' => $key); - \Qiniu\setWithoutEmpty($params, 'fops', $fops); + $params = array('bucket' => $bucket, 'key' => $key, 'fops' => $fops); \Qiniu\setWithoutEmpty($params, 'pipeline', $pipeline); \Qiniu\setWithoutEmpty($params, 'notifyURL', $notify_url); - \Qiniu\setWithoutEmpty($params, 'type', $type); - \Qiniu\setWithoutEmpty($params, 'workflowTemplateID', $workflow_template_id); if ($force) { $params['force'] = 1; } @@ -90,11 +65,10 @@ final class PersistentFop if ($this->config->useHTTPS === true) { $scheme = "https://"; } - $apiHost = $this->getApiHost(); - $url = $scheme . $apiHost . '/pfop/'; + $url = $scheme . Config::API_HOST . '/pfop/'; $headers = $this->auth->authorization($url, $data, 'application/x-www-form-urlencoded'); $headers['Content-Type'] = 'application/x-www-form-urlencoded'; - $response = Client::post($url, $data, $headers, $this->proxy->makeReqOpt()); + $response = Client::post($url, $data, $headers); if (!$response->ok()) { return array(null, new Error($url, $response)); } @@ -103,10 +77,6 @@ final class PersistentFop return array($id, null); } - /** - * @param string $id - * @return array 返回任务状态与可能出现的错误 - */ public function status($id) { $scheme = "http://"; @@ -114,22 +84,11 @@ final class PersistentFop if ($this->config->useHTTPS === true) { $scheme = "https://"; } - $apiHost = $this->getApiHost(); - $url = $scheme . $apiHost . "/status/get/prefop?id=$id"; - $response = Client::get($url, array(), $this->proxy->makeReqOpt()); + $url = $scheme . Config::API_HOST . "/status/get/prefop?id=$id"; + $response = Client::get($url); if (!$response->ok()) { return array(null, new Error($url, $response)); } return array($response->json(), null); } - - private function getApiHost() - { - if (!empty($this->config->zone) && !empty($this->config->zone->apiHost)) { - $apiHost = $this->config->zone->apiHost; - } else { - $apiHost = Config::API_HOST; - } - return $apiHost; - } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Region.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Region.php index 220a5a3c6..eae21d199 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Region.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Region.php @@ -1,11 +1,8 @@ srcUpHosts = $srcUpHosts; @@ -42,18 +36,17 @@ class Region $this->rsfHost = $rsfHost; $this->apiHost = $apiHost; $this->iovipHost = $iovipHost; - $this->ttl = $ttl; } //华东机房 public static function regionHuadong() { $regionHuadong = new Region( - array("up.qiniup.com"), - array('upload.qiniup.com'), - 'rs-z0.qiniuapi.com', - 'rsf-z0.qiniuapi.com', - 'api.qiniuapi.com', + array("up.qiniup.com", 'up-jjh.qiniup.com', 'up-xs.qiniup.com'), + array('upload.qiniup.com', 'upload-jjh.qiniup.com', 'upload-xs.qiniup.com'), + 'rs.qbox.me', + 'rsf.qbox.me', + 'api.qiniu.com', 'iovip.qbox.me' ); return $regionHuadong; @@ -64,9 +57,9 @@ class Region { $qvmRegionHuadong = new Region( array("free-qvm-z0-xs.qiniup.com"), - 'rs-z0.qiniuapi.com', - 'rsf-z0.qiniuapi.com', - 'api.qiniuapi.com', + 'rs.qbox.me', + 'rsf.qbox.me', + 'api.qiniu.com', 'iovip.qbox.me' ); return $qvmRegionHuadong; @@ -77,9 +70,9 @@ class Region { $qvmRegionHuabei = new Region( array("free-qvm-z1-zz.qiniup.com"), - "rs-z1.qiniuapi.com", - "rsf-z1.qiniuapi.com", - "api-z1.qiniuapi.com", + "rs-z1.qbox.me", + "rsf-z1.qbox.me", + "api-z1.qiniu.com", "iovip-z1.qbox.me" ); return $qvmRegionHuabei; @@ -91,9 +84,9 @@ class Region $regionHuabei = new Region( array('up-z1.qiniup.com'), array('upload-z1.qiniup.com'), - "rs-z1.qiniuapi.com", - "rsf-z1.qiniuapi.com", - "api-z1.qiniuapi.com", + "rs-z1.qbox.me", + "rsf-z1.qbox.me", + "api-z1.qiniu.com", "iovip-z1.qbox.me" ); @@ -104,29 +97,16 @@ class Region public static function regionHuanan() { $regionHuanan = new Region( - array('up-z2.qiniup.com'), - array('upload-z2.qiniup.com'), - "rs-z2.qiniuapi.com", - "rsf-z2.qiniuapi.com", - "api-z2.qiniuapi.com", + array('up-z2.qiniup.com', 'up-dg.qiniup.com', 'up-fs.qiniup.com'), + array('upload-z2.qiniup.com', 'upload-dg.qiniup.com', 'upload-fs.qiniup.com'), + "rs-z2.qbox.me", + "rsf-z2.qbox.me", + "api-z2.qiniu.com", "iovip-z2.qbox.me" ); return $regionHuanan; } - //华东2 机房 - public static function regionHuadong2() - { - return new Region( - array('up-cn-east-2.qiniup.com'), - array('upload-cn-east-2.qiniup.com'), - "rs-cn-east-2.qiniuapi.com", - "rsf-cn-east-2.qiniuapi.com", - "api-cn-east-2.qiniuapi.com", - "iovip-cn-east-2.qiniuio.com" - ); - } - //北美机房 public static function regionNorthAmerica() { @@ -134,9 +114,9 @@ class Region $regionNorthAmerica = new Region( array('up-na0.qiniup.com'), array('upload-na0.qiniup.com'), - "rs-na0.qiniuapi.com", - "rsf-na0.qiniuapi.com", - "api-na0.qiniuapi.com", + "rs-na0.qbox.me", + "rsf-na0.qbox.me", + "api-na0.qiniu.com", "iovip-na0.qbox.me" ); return $regionNorthAmerica; @@ -149,81 +129,68 @@ class Region $regionSingapore = new Region( array('up-as0.qiniup.com'), array('upload-as0.qiniup.com'), - "rs-as0.qiniuapi.com", - "rsf-as0.qiniuapi.com", - "api-as0.qiniuapi.com", + "rs-as0.qbox.me", + "rsf-as0.qbox.me", + "api-as0.qiniu.com", "iovip-as0.qbox.me" ); return $regionSingapore; } /* - * GET /v4/query?ak=&bucket= - * @param string $ak - * @param string $bucket - * @param string $ucHost|null - * @param array $backupUcHosts - * @param int $retryTimes - * @param RequestOptions|null $reqOpt - * @return Response + * GET /v2/query?ak=&&bucket= **/ - public static function queryRegion( - $ak, - $bucket, - $ucHost = null, - $backupUcHosts = array(), - $retryTimes = 2, - $reqOpt = null - ) { - $region = new Region(); - if (!$ucHost) { - $ucHost = "https://" . Config::QUERY_REGION_HOST; - } - $url = $ucHost . '/v4/query' . "?ak=$ak&bucket=$bucket"; - if ($reqOpt == null) { - $reqOpt = new RequestOptions(); - } - $reqOpt->middlewares = array( - new RetryDomainsMiddleware( - $backupUcHosts, - $retryTimes - ) - ); - $ret = Client::get($url, array(), $reqOpt); + public static function queryRegion($ak, $bucket) + { + $Region = new Region(); + $url = Config::API_HOST . '/v2/query' . "?ak=$ak&bucket=$bucket"; + $ret = Client::Get($url); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } $r = ($ret->body === null) ? array() : $ret->json(); - if (!is_array($r["hosts"]) || count($r["hosts"]) == 0) { - return array(null, new Error($url, $ret)); + //parse Region; + + $iovipHost = $r['io']['src']['main'][0]; + $Region->iovipHost = $iovipHost; + $accMain = $r['up']['acc']['main'][0]; + array_push($Region->cdnUpHosts, $accMain); + if (isset($r['up']['acc']['backup'])) { + foreach ($r['up']['acc']['backup'] as $key => $value) { + array_push($Region->cdnUpHosts, $value); + } + } + $srcMain = $r['up']['src']['main'][0]; + array_push($Region->srcUpHosts, $srcMain); + if (isset($r['up']['src']['backup'])) { + foreach ($r['up']['src']['backup'] as $key => $value) { + array_push($Region->srcUpHosts, $value); + } } - // parse region; - $regionHost = $r["hosts"][0]; - $region->cdnUpHosts = array_merge($region->cdnUpHosts, $regionHost['up']['domains']); - $region->srcUpHosts = array_merge($region->srcUpHosts, $regionHost['up']['domains']); - - // set specific hosts - $region->iovipHost = $regionHost['io']['domains'][0]; - if (isset($regionHost['rs']['domains']) && count($regionHost['rs']['domains']) > 0) { - $region->rsHost = $regionHost['rs']['domains'][0]; + //set specific hosts + if (strstr($Region->iovipHost, "z1") !== false) { + $Region->rsHost = "rs-z1.qbox.me"; + $Region->rsfHost = "rsf-z1.qbox.me"; + $Region->apiHost = "api-z1.qiniu.com"; + } elseif (strstr($Region->iovipHost, "z2") !== false) { + $Region->rsHost = "rs-z2.qbox.me"; + $Region->rsfHost = "rsf-z2.qbox.me"; + $Region->apiHost = "api-z2.qiniu.com"; + } elseif (strstr($Region->iovipHost, "na0") !== false) { + $Region->rsHost = "rs-na0.qbox.me"; + $Region->rsfHost = "rsf-na0.qbox.me"; + $Region->apiHost = "api-na0.qiniu.com"; + } elseif (strstr($Region->iovipHost, "as0") !== false) { + $Region->rsHost = "rs-as0.qbox.me"; + $Region->rsfHost = "rsf-as0.qbox.me"; + $Region->apiHost = "api-as0.qiniu.com"; } else { - $region->rsHost = Config::RS_HOST; - } - if (isset($regionHost['rsf']['domains']) && count($regionHost['rsf']['domains']) > 0) { - $region->rsfHost = $regionHost['rsf']['domains'][0]; - } else { - $region->rsfHost = Config::RSF_HOST; - } - if (isset($regionHost['api']['domains']) && count($regionHost['api']['domains']) > 0) { - $region->apiHost = $regionHost['api']['domains'][0]; - } else { - $region->apiHost = Config::API_HOST; + $Region->rsHost = "rs.qbox.me"; + $Region->rsfHost = "rsf.qbox.me"; + $Region->apiHost = "api.qiniu.com"; } - // set ttl - $region->ttl = $regionHost['ttl']; - - return $region; + return $Region; } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Rtc/AppClient.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Rtc/AppClient.php index 3f245db2c..4f45aaeba 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Rtc/AppClient.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Rtc/AppClient.php @@ -6,19 +6,17 @@ use Qiniu\Auth; use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\Proxy; class AppClient { private $auth; private $baseURL; - private $proxy; - public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) + public function __construct(Auth $auth) { $this->auth = $auth; + $this->baseURL = sprintf("%s/%s/apps", Config::RTCAPI_HOST, Config::RTCAPI_VERSION); - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -204,7 +202,7 @@ class AppClient { $rtcToken = $this->auth->authorizationV2($url, "GET", null, $cType); $rtcToken['Content-Type'] = $cType; - $ret = Client::get($url, $rtcToken, $this->proxy->makeReqOpt()); + $ret = Client::get($url, $rtcToken); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -215,7 +213,7 @@ class AppClient { $rtcToken = $this->auth->authorizationV2($url, "DELETE", null, $contentType); $rtcToken['Content-Type'] = $contentType; - $ret = Client::delete($url, $rtcToken, $this->proxy->makeReqOpt()); + $ret = Client::delete($url, $rtcToken); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -226,7 +224,7 @@ class AppClient { $rtcToken = $this->auth->authorizationV2($url, "POST", $body, $contentType); $rtcToken['Content-Type'] = $contentType; - $ret = Client::post($url, $body, $rtcToken, $this->proxy->makeReqOpt()); + $ret = Client::post($url, $body, $rtcToken); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Sms/Sms.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Sms/Sms.php index c96409b6b..625ec3044 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Sms/Sms.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Sms/Sms.php @@ -6,19 +6,17 @@ use Qiniu\Auth; use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\Proxy; class Sms { private $auth; private $baseURL; - private $proxy; - public function __construct(Auth $auth, $proxy = null, $proxy_auth = null, $proxy_user_password = null) + public function __construct(Auth $auth) { $this->auth = $auth; + $this->baseURL = sprintf("%s/%s/", Config::SMS_HOST, Config::SMS_VERSION); - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -337,7 +335,7 @@ class Sms { $headers = $this->auth->authorizationV2($url, "GET", null, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::get($url, $headers, $this->proxy->makeReqOpt()); + $ret = Client::get($url, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -348,7 +346,7 @@ class Sms { $headers = $this->auth->authorizationV2($url, "DELETE", null, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::delete($url, $headers, $this->proxy->makeReqOpt()); + $ret = Client::delete($url, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -360,7 +358,7 @@ class Sms $headers = $this->auth->authorizationV2($url, "POST", $body, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); + $ret = Client::post($url, $body, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -372,7 +370,7 @@ class Sms { $headers = $this->auth->authorizationV2($url, "PUT", $body, $contentType); $headers['Content-Type'] = $contentType; - $ret = Client::put($url, $body, $headers, $this->proxy->makeReqOpt()); + $ret = Client::put($url, $body, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ArgusManager.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ArgusManager.php index 51b4200ce..0f2baee2c 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ArgusManager.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ArgusManager.php @@ -7,7 +7,6 @@ use Qiniu\Config; use Qiniu\Zone; use Qiniu\Http\Client; use Qiniu\Http\Error; -use Qiniu\Http\Proxy; /** * 主要涉及了内容审核接口的实现,具体的接口规格可以参考 @@ -18,22 +17,15 @@ final class ArgusManager { private $auth; private $config; - private $proxy; - public function __construct( - Auth $auth, - Config $config = null, - $proxy = null, - $proxy_auth = null, - $proxy_user_password = null - ) { + public function __construct(Auth $auth, Config $config = null) + { $this->auth = $auth; if ($config == null) { $this->config = new Config(); } else { $this->config = $config; } - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -84,6 +76,7 @@ final class ArgusManager $url = $scheme . Config::ARGUS_HOST . "/v3/jobs/video/$jobid"; $response = $this->get($url); if (!$response->ok()) { + print("statusCode: " . $response->statusCode); return array(null, new Error($url, $response)); } return array($response->json(), null); @@ -108,15 +101,16 @@ final class ArgusManager { $headers = $this->auth->authorizationV2($url, 'GET'); - return Client::get($url, $headers, $this->proxy->makeReqOpt()); + return Client::get($url, $headers); } private function post($url, $body) { $headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/json'); $headers['Content-Type'] = 'application/json'; - $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); + $ret = Client::post($url, $body, $headers); if (!$ret->ok()) { + print("statusCode: " . $ret->statusCode); return array(null, new Error($url, $ret)); } $r = ($ret->body === null) ? array() : $ret->json(); diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/BucketManager.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/BucketManager.php index bfca4fc1d..93fa267da 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/BucketManager.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/BucketManager.php @@ -6,8 +6,6 @@ use Qiniu\Auth; use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\Proxy; -use Qiniu\Http\Response; /** * 主要涉及了空间资源管理及批量操作接口的实现,具体的接口规格可以参考 @@ -18,22 +16,15 @@ final class BucketManager { private $auth; private $config; - private $proxy; - public function __construct( - Auth $auth, - Config $config = null, - $proxy = null, - $proxy_auth = null, - $proxy_user_password = null - ) { + public function __construct(Auth $auth, Config $config = null) + { $this->auth = $auth; if ($config == null) { $this->config = new Config(); } else { $this->config = $config; } - $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password); } /** @@ -48,7 +39,7 @@ final class BucketManager if ($shared === true) { $includeShared = "true"; } - return $this->getV2($this->config->getUcHost() . '/buckets?shared=' . $includeShared); + return $this->rsGet('/buckets?shared=' . $includeShared); } /** @@ -80,7 +71,7 @@ final class BucketManager public function createBucket($name, $region = 'z0') { $path = '/mkbucketv3/' . $name . '/region/' . $region; - return $this->postV2($this->config->getUcHost() . $path, null); + return $this->rsPost($path, null); } /** @@ -94,7 +85,7 @@ final class BucketManager public function deleteBucket($name) { $path = '/drop/' . $name; - return $this->postV2($this->config->getUcHost() . $path, null); + return $this->rsPost($path, null); } /** @@ -105,7 +96,7 @@ final class BucketManager */ public function domains($bucket) { - return $this->ucGet('/v2/domains?tbl=' . $bucket); + return $this->apiGet('/v6/domain/list?tbl=' . $bucket); } /** @@ -158,14 +149,13 @@ final class BucketManager \Qiniu\setWithoutEmpty($query, 'marker', $marker); \Qiniu\setWithoutEmpty($query, 'limit', $limit); \Qiniu\setWithoutEmpty($query, 'delimiter', $delimiter); - return $this->rsfGet($bucket, '/list?' . http_build_query($query)); + $url = $this->getRsfHost() . '/list?' . http_build_query($query); + return $this->getV2($url); } /** * 列取空间的文件列表 * - * @deprecated API 可能返回仅包含 marker,不包含 item 或 dir 的项,请使用 {@link listFiles} - * * @param string $bucket 空间名 * @param string $prefix 列举前缀 * @param string $marker 列举标识符 @@ -191,20 +181,9 @@ final class BucketManager \Qiniu\setWithoutEmpty($query, 'delimiter', $delimiter); \Qiniu\setWithoutEmpty($query, 'skipconfirm', $skipconfirm); $path = '/v2/list?' . http_build_query($query); - - list($host, $err) = $this->config->getRsfHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); - } - - $url = $host . $path; + $url = $this->getRsfHost() . $path; $headers = $this->auth->authorizationV2($url, 'POST', null, 'application/x-www-form-urlencoded'); - $ret = Client::post($url, null, $headers, $this->proxy->makeReqOpt()); + $ret = Client::post($url, null, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -216,23 +195,18 @@ final class BucketManager /** * 增加bucket生命规则 * - * @param string $bucket - * 空间名 - * @param string $name - * 规则名称 bucket 内唯一,长度小于50,不能为空,只能为字母、数字、下划线 - * @param string $prefix - * 同一个 bucket 里面前缀不能重复 - * @param int $delete_after_days - * 指定上传文件多少天后删除,指定为0表示不删除,大于0表示多少天后删除。 - * 需大于 to_line_after_days - * @param int $to_line_after_days - * 指定文件上传多少天后转低频存储。指定为0表示不转低频存储 - * @param int $to_archive_ir_after_days - * 指定文件上传多少天后转归档直读。指定为0表示不转归档直读 - * @param int $to_archive_after_days - * 指定文件上传多少天后转归档存储。指定为0表示不转归档存储 - * @param int $to_deep_archive_after_days - * 指定文件上传多少天后转深度归档存储。指定为0表示不转深度归档存储 + * @param string $bucket 空间名 + * @param string $name 规则名称 bucket 内唯一,长度小于50,不能为空,只能为 + * 字母、数字、下划线 + * @param string $prefix 同一个 bucket 里面前缀不能重复 + * @param int $delete_after_days 指定上传文件多少天后删除,指定为0表示不删除, + * 大于0表示多少天后删除,需大于 to_line_after_days + * @param int $to_line_after_days 指定文件上传多少天后转低频存储。指定为0表示 + * 不转低频存储,小于0表示上传的文件立即变低频存储 + * @param int $to_archive_after_days 指定文件上传多少天后转归档存储。指定为0表示 + * 不转归档存储,小于0表示上传的文件立即变归档存储 + * @param int $to_deep_archive_after_days 指定文件上传多少天后转深度归档存储。指定为0表示 + * 不转深度归档存储,小于0表示上传的文件立即变深度归档存储 * @return array */ public function bucketLifecycleRule( @@ -242,8 +216,7 @@ final class BucketManager $delete_after_days = null, $to_line_after_days = null, $to_archive_after_days = null, - $to_deep_archive_after_days = null, - $to_archive_ir_after_days = null + $to_deep_archive_after_days = null ) { $path = '/rules/add'; $params = array(); @@ -262,9 +235,6 @@ final class BucketManager if ($to_line_after_days) { $params['to_line_after_days'] = $to_line_after_days; } - if ($to_archive_ir_after_days) { - $params['to_archive_ir_after_days'] = $to_archive_ir_after_days; - } if ($to_archive_after_days) { $params['to_archive_after_days'] = $to_archive_after_days; } @@ -279,23 +249,18 @@ final class BucketManager /** * 更新bucket生命规则 * - * @param string $bucket - * 空间名 - * @param string $name - * 规则名称 bucket 内唯一,长度小于50,不能为空,只能为字母、数字、下划线 - * @param string $prefix - * 同一个 bucket 里面前缀不能重复 - * @param int $delete_after_days - * 指定上传文件多少天后删除,指定为0表示不删除,大于0表示多少天后删除 - * 需大于 to_line_after_days - * @param int $to_line_after_days - * 指定文件上传多少天后转低频存储。指定为0表示不转低频存储 - * @param int $to_archive_ir_after_days - * 指定文件上传多少天后转归档只读。指定为0表示不转归档只读 - * @param int $to_archive_after_days - * 指定文件上传多少天后转归档存储。指定为0表示不转归档存储 - * @param int $to_deep_archive_after_days - * 指定文件上传多少天后转深度归档存储。指定为0表示不转深度归档存储 + * @param string $bucket 空间名 + * @param string $name 规则名称 bucket 内唯一,长度小于50,不能为空,只能为字母、 + * 数字、下划线 + * @param string $prefix 同一个 bucket 里面前缀不能重复 + * @param int $delete_after_days 指定上传文件多少天后删除,指定为0表示不删除, + * 大于0表示多少天后删除,需大于 to_line_after_days + * @param int $to_line_after_days 指定文件上传多少天后转低频存储。指定为0表示不 + * 转低频存储,小于0表示上传的文件立即变低频存储 + * @param int $to_archive_after_days 指定文件上传多少天后转归档存储。指定为0表示 + * 不转归档存储,小于0表示上传的文件立即变归档存储 + * @param int $to_deep_archive_after_days 指定文件上传多少天后转深度归档存储。指定为0表示 + * 不转深度归档存储,小于0表示上传的文件立即变深度归档存储 * @return array */ public function updateBucketLifecycleRule( @@ -305,8 +270,7 @@ final class BucketManager $delete_after_days = null, $to_line_after_days = null, $to_archive_after_days = null, - $to_deep_archive_after_days = null, - $to_archive_ir_after_days = null + $to_deep_archive_after_days = null ) { $path = '/rules/update'; $params = array(); @@ -325,9 +289,6 @@ final class BucketManager if ($to_line_after_days) { $params['to_line_after_days'] = $to_line_after_days; } - if ($to_archive_ir_after_days) { - $params['to_archive_ir_after_days'] = $to_archive_ir_after_days; - } if ($to_archive_after_days) { $params['to_archive_after_days'] = $to_archive_after_days; } @@ -611,7 +572,7 @@ final class BucketManager public function putBucketQuota($bucket, $size, $count) { $path = '/setbucketquota/' . $bucket . '/size/' . $size . '/count/' . $count; - return $this->apiPost($bucket, $path); + return $this->apiPost($path, null); } /** @@ -623,7 +584,7 @@ final class BucketManager public function getBucketQuota($bucket) { $path = '/getbucketquota/' . $bucket; - return $this->apiPost($bucket, $path); + return $this->apiPost($path, null); } /** @@ -638,7 +599,7 @@ final class BucketManager public function stat($bucket, $key) { $path = '/stat/' . \Qiniu\entry($bucket, $key); - return $this->rsGet($bucket, $path); + return $this->rsGet($path); } /** @@ -653,7 +614,7 @@ final class BucketManager public function delete($bucket, $key) { $path = '/delete/' . \Qiniu\entry($bucket, $key); - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } /** @@ -689,7 +650,7 @@ final class BucketManager if ($force === true) { $path .= '/force/true'; } - return $this->rsPost($from_bucket, $path); + return $this->rsPost($path); } /** @@ -711,7 +672,7 @@ final class BucketManager if ($force) { $path .= '/force/true'; } - return $this->rsPost($from_bucket, $path); + return $this->rsPost($path); } /** @@ -729,7 +690,7 @@ final class BucketManager $resource = \Qiniu\entry($bucket, $key); $encode_mime = \Qiniu\base64_urlSafeEncode($mime); $path = '/chgm/' . $resource . '/mime/' . $encode_mime; - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } @@ -738,12 +699,7 @@ final class BucketManager * * @param string $bucket 待操作资源所在空间 * @param string $key 待操作资源文件名 - * @param int $fileType 对象存储类型 - * 0 表示标准存储; - * 1 表示低频存储; - * 2 表示归档存储; - * 3 表示深度归档存储; - * 4 表示归档直读存储; + * @param int $fileType 0 表示标准存储;1 表示低频存储;2 表示归档存储;3 表示深度归档存储 * * @return array * @link https://developer.qiniu.com/kodo/api/3710/chtype @@ -752,7 +708,7 @@ final class BucketManager { $resource = \Qiniu\entry($bucket, $key); $path = '/chtype/' . $resource . '/type/' . $fileType; - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } /** @@ -769,7 +725,7 @@ final class BucketManager { $resource = \Qiniu\entry($bucket, $key); $path = '/restoreAr/' . $resource . '/freezeAfterDays/' . $freezeAfterDays; - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } /** @@ -786,7 +742,7 @@ final class BucketManager { $resource = \Qiniu\entry($bucket, $key); $path = '/chstatus/' . $resource . '/status/' . $status; - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } /** @@ -807,10 +763,9 @@ final class BucketManager $path = '/fetch/' . $resource . '/to/' . $to; $ak = $this->auth->getAccessKey(); - - - list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket, $this->proxy->makeReqOpt()); - if ($err != null) { + try { + $ioHost = $this->config->getIovipHost($ak, $bucket); + } catch (\Exception $err) { return array(null, $err); } @@ -831,12 +786,7 @@ final class BucketManager * @param string $callbackbody 回调Body * @param string $callbackbodytype 回调Body内容类型,默认为"application/x-www-form-urlencoded" * @param string $callbackhost 回调时使用的Host - * @param int $file_type 存储文件类型 - * 0:标准存储(默认) - * 1:低频存储 - * 2:归档存储 - * 3:深度归档存储 - * 4:归档直读存储 + * @param int $file_type 存储文件类型 0:标准存储(默认),1:低频存储,2:归档存储 * @param bool $ignore_same_key 如果空间中已经存在同名文件则放弃本次抓取 * @return array * @link https://developer.qiniu.com/kodo/api/4097/asynch-fetch @@ -870,7 +820,15 @@ final class BucketManager \Qiniu\setWithoutEmpty($params, 'ignore_same_key', $ignore_same_key); $data = json_encode($params); - return $this->apiPost($bucket, $path, $data); + $ak = $this->auth->getAccessKey(); + try { + $apiHost = $this->config->getApiHost($ak, $bucket); + } catch (\Exception $err) { + return array(null, $err); + } + $url = $apiHost . $path; + + return $this->postV2($url, $data); } @@ -890,7 +848,7 @@ final class BucketManager $scheme = "https://"; } - $url = $scheme . "api-" . $zone . ".qiniuapi.com/sisyphus/fetch?id=" . $id; + $url = $scheme . "api-" . $zone . ".qiniu.com/sisyphus/fetch?id=" . $id; list($ret, $err) = $this->getV2($url); @@ -916,9 +874,9 @@ final class BucketManager $path = '/prefetch/' . $resource; $ak = $this->auth->getAccessKey(); - list($ioHost, $err) = $this->config->getIovipHostV2($ak, $bucket, $this->proxy->makeReqOpt()); - - if ($err != null) { + try { + $ioHost = $this->config->getIovipHost($ak, $bucket); + } catch (\Exception $err) { return array(null, $err); } @@ -944,25 +902,8 @@ final class BucketManager */ public function batch($operations) { - $scheme = "http://"; - if ($this->config->useHTTPS === true) { - $scheme = "https://"; - } $params = 'op=' . implode('&op=', $operations); - $errResp = new Response(0, 0); - if (count($operations) <= 0) { - $errResp->error = 'empty operations'; - return array(null, new Error($scheme . '/batch', $errResp)); - } - $bucket = ''; - foreach ($operations as $op) { - $segments = explode('/', $op); - if (count($segments) < 3) { - continue; - } - list($bucket,) = \Qiniu\decodeEntry($segments[2]); - } - return $this->rsPost($bucket, '/batch', $params); + return $this->rsPost('/batch', $params); } /** @@ -979,196 +920,85 @@ final class BucketManager { $entry = \Qiniu\entry($bucket, $key); $path = "/deleteAfterDays/$entry/$days"; - return $this->rsPost($bucket, $path); + return $this->rsPost($path); } - /** - * 更新 object 生命周期 - * - * @param string $bucket 空间名 - * @param string $key 目标资源 - * @param int $to_line_after_days 多少天后将文件转为低频存储。 - * -1 表示取消已设置的转低频存储的生命周期规则; - * 0 表示不修改转低频生命周期规则。 - * @param int $to_archive_ir_after_days 多少天后转为归档直读存储。 - * -1 表示取消已设置的转归档直读存储的生命周期规则; - * 0 表示不修改转归档直读生命周期规则。 - * @param int $to_archive_after_days 多少天后将文件转为归档存储。 - * -1 表示取消已设置的转归档存储的生命周期规则; - * 0 表示不修改转归档生命周期规则。 - * @param int $to_deep_archive_after_days 多少天后将文件转为深度归档存储。 - * -1 表示取消已设置的转深度归档存储的生命周期规则; - * 0 表示不修改转深度归档生命周期规则。 - * @param int $delete_after_days 多少天后将文件删除。 - * -1 表示取消已设置的删除存储的生命周期规则; - * 0 表示不修改删除存储的生命周期规则。 - * @return array - */ - public function setObjectLifecycle( - $bucket, - $key, - $to_line_after_days = 0, - $to_archive_after_days = 0, - $to_deep_archive_after_days = 0, - $delete_after_days = 0, - $to_archive_ir_after_days = 0 - ) { - return $this->setObjectLifecycleWithCond( - $bucket, - $key, - null, - $to_line_after_days, - $to_archive_after_days, - $to_deep_archive_after_days, - $delete_after_days, - $to_archive_ir_after_days - ); - } - - /** - * 更新 object 生命周期 - * - * @param string $bucket 空间名 - * @param string $key 目标资源 - * @param int $to_line_after_days 多少天后将文件转为低频存储。 - * 设置为 -1 表示取消已设置的转低频存储的生命周期规则; - * 0 表示不修改转低频生命周期规则。 - * @param int $to_archive_ir_after_days 多少天后将文件转为归档直读存储。 - * 设置为 -1 表示取消已设置的转归档直读存储的生命周期规则; - * 0 表示不修改转归档直读生命周期规则。 - * @param int $to_archive_after_days 多少天后将文件转为归档存储。 - * -1 表示取消已设置的转归档存储的生命周期规则; - * 0 表示不修改转归档生命周期规则。 - * @param int $to_deep_archive_after_days 多少天后将文件转为深度归档存储。 - * -1 表示取消已设置的转深度归档存储的生命周期规则; - * 0 表示不修改转深度归档生命周期规则。 - * @param int $delete_after_days 多少天后将文件删除。 - * -1 表示取消已设置的删除存储的生命周期规则; - * 0 表示不修改删除存储的生命周期规则。 - * @param array $cond 匹配条件,只有条件匹配才会设置成功。 - * 目前支持:hash、mime、fsize、putTime - * @return array - */ - public function setObjectLifecycleWithCond( - $bucket, - $key, - $cond = null, - $to_line_after_days = 0, - $to_archive_after_days = 0, - $to_deep_archive_after_days = 0, - $delete_after_days = 0, - $to_archive_ir_after_days = 0 - ) { - $encodedEntry = \Qiniu\entry($bucket, $key); - $path = '/lifecycle/' . $encodedEntry . - '/toIAAfterDays/' . $to_line_after_days . - '/toArchiveIRAfterDays/' . $to_archive_ir_after_days . - '/toArchiveAfterDays/' . $to_archive_after_days . - '/toDeepArchiveAfterDays/' . $to_deep_archive_after_days . - '/deleteAfterDays/' . $delete_after_days; - if ($cond != null) { - $condStrArr = array(); - foreach ($cond as $key => $value) { - array_push($condStrArr, $key . '=' . $value); - } - $condStr = implode('&', $condStrArr); - $path .= '/cond' . \Qiniu\base64_urlSafeEncode($condStr); - } - return $this->rsPost($bucket, $path); - } - - private function rsfGet($bucket, $path) + private function getRsfHost() { - list($host, $err) = $this->config->getRsfHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); + $scheme = "http://"; + if ($this->config->useHTTPS === true) { + $scheme = "https://"; } - - return $this->getV2($host . $path); + return $scheme . Config::RSF_HOST; } - private function rsGet($bucket, $path) + private function getRsHost() { - list($host, $err) = $this->config->getRsHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); + $scheme = "http://"; + if ($this->config->useHTTPS === true) { + $scheme = "https://"; } - - return $this->getV2($host . $path); + return $scheme . Config::RS_HOST; } - private function rsPost($bucket, $path, $body = null) + private function getApiHost() { - list($host, $err) = $this->config->getRsHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); + $scheme = "http://"; + if ($this->config->useHTTPS === true) { + $scheme = "https://"; } - - return $this->postV2($host . $path, $body); + return $scheme . Config::API_HOST; } - private function apiGet($bucket, $path) + private function getUcHost() { - list($host, $err) = $this->config->getApiHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); + $scheme = "http://"; + if ($this->config->useHTTPS === true) { + $scheme = "https://"; } - - return $this->getV2($host . $path); + return $scheme . Config::UC_HOST; } - private function apiPost($bucket, $path, $body = null) + private function rsPost($path, $body = null) { - - list($host, $err) = $this->config->getApiHostV2( - $this->auth->getAccessKey(), - $bucket, - $this->proxy->makeReqOpt() - ); - - if ($err != null) { - return array(null, $err); - } - - return $this->postV2($host . $path, $body); + $url = $this->getRsHost() . $path; + return $this->postV2($url, $body); } - private function ucGet($path) + private function apiPost($path, $body = null) { - $url = $this->config->getUcHost() . $path; - return $this->getV2($url); + $url = $this->getApiHost() . $path; + return $this->postV2($url, $body); } private function ucPost($path, $body = null) { - $url = $this->config->getUcHost() . $path; + $url = $this->getUcHost() . $path; return $this->postV2($url, $body); } + private function ucGet($path) + { + $url = $this->getUcHost() . $path; + return $this->getV2($url); + } + + private function apiGet($path) + { + $url = $this->getApiHost() . $path; + return $this->getV2($url); + } + + private function rsGet($path) + { + $url = $this->getRsHost() . $path; + return $this->getV2($url); + } + private function getV2($url) { $headers = $this->auth->authorizationV2($url, 'GET', null, 'application/x-www-form-urlencoded'); - $ret = Client::get($url, $headers, $this->proxy->makeReqOpt()); + $ret = Client::get($url, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -1178,7 +1008,7 @@ final class BucketManager private function postV2($url, $body) { $headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/x-www-form-urlencoded'); - $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt()); + $ret = Client::post($url, $body, $headers); if (!$ret->ok()) { return array(null, new Error($url, $ret)); } @@ -1224,50 +1054,6 @@ final class BucketManager return $data; } - /** - * @param string $bucket 空间名 - * @param array $keys 目标资源 - * @param int $to_line_after_days 多少天后将文件转为低频存储。 - * -1 表示取消已设置的转低频存储的生命周期规则; - * 0 表示不修改转低频生命周期规则。 - * @param int $to_archive_ir_after_days 多少天后将文件转为归档直读。 - * -1 表示取消已设置的转归档只读的生命周期规则; - * 0 表示不修改转归档只读周期规则。 - * @param int $to_archive_after_days 多少天后将文件转为归档存储。 - * -1 表示取消已设置的转归档存储的生命周期规则; - * 0 表示不修改转归档生命周期规则。 - * @param int $to_deep_archive_after_days 多少天后将文件转为深度归档存储。 - * -1 表示取消已设置的转深度归档存储的生命周期规则; - * 0 表示不修改转深度归档生命周期规则。 - * @param int $delete_after_days 多少天后将文件删除。 - * -1 表示取消已设置的删除存储的生命周期规则; - * 0 表示不修改删除存储的生命周期规则。 - * - * @retrun array - */ - public static function buildBatchSetObjectLifecycle( - $bucket, - $keys, - $to_line_after_days, - $to_archive_after_days, - $to_deep_archive_after_days, - $delete_after_days, - $to_archive_ir_after_days = 0 - ) { - $result = array(); - foreach ($keys as $key) { - $encodedEntry = \Qiniu\entry($bucket, $key); - $op = '/lifecycle/' . $encodedEntry . - '/toIAAfterDays/' . $to_line_after_days . - '/toArchiveIRAfterDays/' . $to_archive_ir_after_days . - '/toArchiveAfterDays/' . $to_archive_after_days . - '/toDeepArchiveAfterDays/' . $to_deep_archive_after_days . - '/deleteAfterDays/' . $delete_after_days; - array_push($result, $op); - } - return $result; - } - public static function buildBatchChangeMime($bucket, $key_mime_pairs) { $data = array(); diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/FormUploader.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/FormUploader.php index d68654d8c..453cc389f 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/FormUploader.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/FormUploader.php @@ -5,7 +5,6 @@ namespace Qiniu\Storage; use Qiniu\Config; use Qiniu\Http\Error; use Qiniu\Http\Client; -use Qiniu\Http\RequestOptions; final class FormUploader { @@ -18,10 +17,10 @@ final class FormUploader * @param string $data 上传二进制流 * @param Config $config 上传配置 * @param string $params 自定义变量,规格参考 - * {@link https://developer.qiniu.com/kodo/manual/1235/vars#xvar} + * https://developer.qiniu.com/kodo/manual/1235/vars#xvar * @param string $mime 上传数据的mimeType + * * @param string $fname - * @param RequestOptions $reqOpt * * @return array 包含已上传文件的信息,类似: * [ @@ -36,12 +35,8 @@ final class FormUploader $config, $params, $mime, - $fname, - $reqOpt = null + $fname ) { - if ($reqOpt == null) { - $reqOpt = new RequestOptions(); - } $fields = array('token' => $upToken); if ($key === null) { } else { @@ -62,22 +57,13 @@ final class FormUploader return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); - if ($err != null) { + try { + $upHost = $config->getUpHost($accessKey, $bucket); + } catch (\Exception $err) { return array(null, $err); } - - $response = Client::multipartPost( - $upHost, - $fields, - 'file', - $fname, - $data, - $mime, - array(), - $reqOpt - ); + $response = Client::multipartPost($upHost, $fields, 'file', $fname, $data, $mime); if (!$response->ok()) { return array(null, new Error($upHost, $response)); } @@ -107,12 +93,9 @@ final class FormUploader $filePath, $config, $params, - $mime, - $reqOpt = null + $mime ) { - if ($reqOpt == null) { - $reqOpt = new RequestOptions(); - } + $fields = array('token' => $upToken, 'file' => self::createFile($filePath, $mime)); if ($key !== null) { @@ -134,12 +117,13 @@ final class FormUploader return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); - if ($err != null) { + try { + $upHost = $config->getUpHost($accessKey, $bucket); + } catch (\Exception $err) { return array(null, $err); } - $response = Client::post($upHost, $fields, $headers, $reqOpt); + $response = Client::post($upHost, $fields, $headers); if (!$response->ok()) { return array(null, new Error($upHost, $response)); } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ResumeUploader.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ResumeUploader.php index 00e88ef28..eedc9afe8 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ResumeUploader.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/ResumeUploader.php @@ -6,7 +6,6 @@ use Qiniu\Config; use Qiniu\Http\Client; use Qiniu\Http\Error; use Qiniu\Enum\SplitUploadVersion; -use Qiniu\Http\RequestOptions; /** * 断点续上传类, 该类主要实现了断点续上传中的分块上传, @@ -32,26 +31,20 @@ final class ResumeUploader private $resumeRecordFile; private $version; private $partSize; - /** - * @var RequestOptions - */ - private $reqOpt; /** * 上传二进制流到七牛 * * @param string $upToken 上传凭证 * @param string $key 上传文件名 - * @param resource $inputStream 上传二进制流 - * @param int $size 上传流的大小 - * @param array $params 自定义变量 + * @param string $inputStream 上传二进制流 + * @param string $size 上传流的大小 + * @param string $params 自定义变量 * @param string $mime 上传数据的mimeType * @param Config $config * @param string $resumeRecordFile 断点续传的已上传的部分信息记录文件 * @param string $version 分片上传版本 目前支持v1/v2版本 默认v1 - * @param int $partSize 分片上传v2字段 默认大小为4MB 分片大小范围为1 MB - 1 GB - * @param RequestOptions $reqOpt 分片上传v2字段 默认大小为4MB 分片大小范围为1 MB - 1 GB - * @throws \Exception + * @param string $partSize 分片上传v2字段 默认大小为4MB 分片大小范围为1 MB - 1 GB * * @link http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar */ @@ -65,8 +58,7 @@ final class ResumeUploader $config, $resumeRecordFile = null, $version = 'v1', - $partSize = config::BLOCK_SIZE, - $reqOpt = null + $partSize = config::BLOCK_SIZE ) { $this->upToken = $upToken; @@ -76,16 +68,11 @@ final class ResumeUploader $this->params = $params; $this->mime = $mime; $this->contexts = array(); - $this->finishedEtags = array("etags" => array(), "uploadId" => "", "expiredAt" => 0, "uploaded" => 0); + $this->finishedEtags = array("etags"=>array(), "uploadId"=>"", "expiredAt"=>0, "uploaded"=>0); $this->config = $config; $this->resumeRecordFile = $resumeRecordFile ? $resumeRecordFile : null; $this->partSize = $partSize ? $partSize : config::BLOCK_SIZE; - if ($reqOpt === null) { - $reqOpt = new RequestOptions(); - } - $this->reqOpt = $reqOpt; - try { $this->version = SplitUploadVersion::from($version ? $version : 'v1'); } catch (\Exception $e) { @@ -98,7 +85,7 @@ final class ResumeUploader return array(null, $err); } - list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt); + $upHost = $config->getUpHost($accessKey, $bucket); if ($err != null) { throw new \Exception($err->message(), 1); } @@ -107,15 +94,17 @@ final class ResumeUploader /** * 上传操作 - * @param $fname string 文件名 - * - * @throws \Exception */ public function upload($fname) { - $blkputRets = null; + $uploaded = 0; + if ($this->version == SplitUploadVersion::V2) { + $partNumber = 1; + $encodedObjectName = $this->key? \Qiniu\base64_urlSafeEncode($this->key) : '~'; + }; // get upload record from resumeRecordFile if ($this->resumeRecordFile != null) { + $blkputRets = null; if (file_exists($this->resumeRecordFile)) { $stream = fopen($this->resumeRecordFile, 'r'); if ($stream) { @@ -140,209 +129,54 @@ final class ResumeUploader } else { error_log("resumeFile not exists"); } - } - if ($this->version == SplitUploadVersion::V1) { - return $this->uploadV1($fname, $blkputRets); - } elseif ($this->version == SplitUploadVersion::V2) { - return $this->uploadV2($fname, $blkputRets); - } else { - throw new \Exception("only support v1/v2 now!"); - } - } - - /** - * @param string $fname 文件名 - * @param null|array $blkputRets - * - * @throws \Exception - */ - private function uploadV1($fname, $blkputRets = null) - { - // 尝试恢复恢复已上传的数据 - $isResumeUpload = $blkputRets !== null; - $this->contexts = array(); - - if ($blkputRets) { - if (isset($blkputRets['contexts']) && isset($blkputRets['uploaded']) && - is_array($blkputRets['contexts']) && is_int($blkputRets['uploaded']) - ) { - $this->contexts = array_map(function ($ctx) { - if (is_array($ctx)) { - return $ctx; - } else { - // 兼容旧版本(旧版本没有存储 expireAt) - return array( - "ctx" => $ctx, - "expiredAt" => 0, - ); + if ($blkputRets) { + if ($this->version == SplitUploadVersion::V1) { + if (isset($blkputRets['contexts']) && isset($blkputRets['uploaded']) && + is_array($blkputRets['contexts']) && is_int($blkputRets['uploaded'])) { + $this->contexts = $blkputRets['contexts']; + $uploaded = $blkputRets['uploaded']; } - }, $blkputRets['contexts']); - } - } - - // 上传分片 - $uploaded = 0; - while ($uploaded < $this->size) { - $blockSize = $this->blockSize($uploaded); - $blockIndex = $uploaded / $this->partSize; - if (!is_int($blockIndex)) { - throw new \Exception("v1 part size changed"); - } - // 如果已上传该分片且没有过期 - if (isset($this->contexts[$blockIndex]) && $this->contexts[$blockIndex]["expiredAt"] >= time()) { - $uploaded += $blockSize; - fseek($this->inputStream, $blockSize, SEEK_CUR); - continue; - } - $data = fread($this->inputStream, $blockSize); - if ($data === false) { - throw new \Exception("file read failed", 1); - } - $crc = \Qiniu\crc32_data($data); - $response = $this->makeBlock($data, $blockSize); - - - $ret = null; - if ($response->ok() && $response->json() != null) { - $ret = $response->json(); - } - if ($response->statusCode < 0) { - list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken); - if ($err != null) { - return array(null, $err); - } - list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket, $this->reqOpt); - if ($err != null) { - return array(null, $err); - } - $this->host = $upHostBackup; - } - - if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) { - $response = $this->makeBlock($data, $blockSize); - $ret = $response->json(); - } - if (!$response->ok() || !isset($ret['crc32']) || $crc != $ret['crc32']) { - return array(null, new Error($this->currentUrl, $response)); - } - - // 如果可以在已上传取到说明是过期分片直接修改已上传信息,否则是新的片添加到已上传分片尾部 - if (isset($this->contexts[$blockIndex])) { - $this->contexts[$blockIndex] = array( - 'ctx' => $ret['ctx'], - 'expiredAt' => $ret['expired_at'], - ); - } else { - array_push($this->contexts, array( - 'ctx' => $ret['ctx'], - 'expiredAt' => $ret['expired_at'], - )); - } - $uploaded += $blockSize; - - // 记录断点 - if ($this->resumeRecordFile !== null) { - $recordData = array( - 'contexts' => $this->contexts, - 'uploaded' => $uploaded - ); - $recordData = json_encode($recordData); - - if ($recordData) { - $isWritten = file_put_contents($this->resumeRecordFile, $recordData); - if ($isWritten === false) { - error_log("write resumeRecordFile failed"); + } elseif ($this->version == SplitUploadVersion::V2) { + if (isset($blkputRets["etags"]) && isset($blkputRets["uploadId"]) && + isset($blkputRets["expiredAt"]) && $blkputRets["expiredAt"] > time() + && $blkputRets["uploaded"] > 0 && is_array($blkputRets["etags"]) && + is_string($blkputRets["uploadId"]) && is_int($blkputRets["expiredAt"])) { + $this->finishedEtags['etags'] = $blkputRets["etags"]; + $this->finishedEtags["uploadId"] = $blkputRets["uploadId"]; + $this->finishedEtags["expiredAt"] = $blkputRets["expiredAt"]; + $this->finishedEtags["uploaded"] = $blkputRets["uploaded"]; + $uploaded = $blkputRets["uploaded"]; + $partNumber = count($this->finishedEtags["etags"]) + 1; + } else { + $this->makeInitReq($encodedObjectName); } } else { - error_log('resumeRecordData encode failed'); + throw new \Exception("only support v1/v2 now!"); + } + } else { + if ($this->version == SplitUploadVersion::V2) { + $this->makeInitReq($encodedObjectName); } } - } - - // 完成上传 - list($ret, $err) = $this->makeFile($fname); - if ($err !== null) { - $response = $err->getResponse(); - if ($isResumeUpload && $response->statusCode === 701) { - fseek($this->inputStream, 0); - return $this->uploadV1($fname); - } - } - return array($ret, $err); - } - - /** - * @param string $fname 文件名 - * @param null|array $blkputRets - * - * @throws \Exception - */ - private function uploadV2($fname, $blkputRets = null) - { - $uploaded = 0; - $partNumber = 1; - $encodedObjectName = $this->key ? \Qiniu\base64_urlSafeEncode($this->key) : '~'; - $isResumeUpload = $blkputRets !== null; - - // 初始化 upload id - $err = null; - if ($blkputRets) { - if (isset($blkputRets["etags"]) && isset($blkputRets["uploadId"]) && - isset($blkputRets["expiredAt"]) && $blkputRets["expiredAt"] > time() && - $blkputRets["uploaded"] > 0 && is_array($blkputRets["etags"]) && - is_string($blkputRets["uploadId"]) && is_int($blkputRets["expiredAt"]) - ) { - $this->finishedEtags['etags'] = $blkputRets["etags"]; - $this->finishedEtags["uploadId"] = $blkputRets["uploadId"]; - $this->finishedEtags["expiredAt"] = $blkputRets["expiredAt"]; - $this->finishedEtags["uploaded"] = $blkputRets["uploaded"]; - $uploaded = $blkputRets["uploaded"]; - $partNumber = count($this->finishedEtags["etags"]) + 1; - } else { - $err = $this->makeInitReq($encodedObjectName); - } } else { - $err = $this->makeInitReq($encodedObjectName); - } - if ($err != null) { - return array(null, $err); + // init a Multipart Upload task if choose v2 + if ($this->version == SplitUploadVersion::V2) { + $this->makeInitReq($encodedObjectName); + } } - // 上传分片 - fseek($this->inputStream, $uploaded); while ($uploaded < $this->size) { $blockSize = $this->blockSize($uploaded); $data = fread($this->inputStream, $blockSize); if ($data === false) { throw new \Exception("file read failed", 1); } - $md5 = md5($data); - $response = $this->uploadPart( - $data, - $partNumber, - $this->finishedEtags["uploadId"], - $encodedObjectName, - $md5 - ); - - $ret = null; - if ($response->ok() && $response->json() != null) { - $ret = $response->json(); - } - if ($response->statusCode < 0) { - list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken); - if ($err != null) { - return array(null, $err); - } - list($upHostBackup, $err) = $this->config->getUpBackupHostV2($accessKey, $bucket, $this->reqOpt); - if ($err != null) { - return array(null, $err); - } - $this->host = $upHostBackup; - } - - if ($response->needRetry() || !isset($ret['md5']) || $md5 != $ret['md5']) { + if ($this->version == SplitUploadVersion::V1) { + $crc = \Qiniu\crc32_data($data); + $response = $this->makeBlock($data, $blockSize); + } elseif ($this->version == SplitUploadVersion::V2) { + $md5 = md5($data); $response = $this->uploadPart( $data, $partNumber, @@ -350,23 +184,72 @@ final class ResumeUploader $encodedObjectName, $md5 ); + } else { + throw new \Exception("only support v1/v2 now!"); + } + + $ret = null; + if ($response->ok() && $response->json() != null) { $ret = $response->json(); } - if ($isResumeUpload && $response->statusCode === 612) { - return $this->uploadV2($fname); + if ($response->statusCode < 0) { + list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken); + if ($err != null) { + return array(null, $err); + } + $upHostBackup = $this->config->getUpBackupHost($accessKey, $bucket); + $this->host = $upHostBackup; } - if (!$response->ok() || !isset($ret['md5']) || $md5 != $ret['md5']) { - return array(null, new Error($this->currentUrl, $response)); + + if ($this->version == SplitUploadVersion::V1) { + if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) { + $response = $this->makeBlock($data, $blockSize); + $ret = $response->json(); + } + + if (!$response->ok() || !isset($ret['crc32']) || $crc != $ret['crc32']) { + return array(null, new Error($this->currentUrl, $response)); + } + array_push($this->contexts, $ret['ctx']); + } elseif ($this->version == SplitUploadVersion::V2) { + if ($response->needRetry() || !isset($ret['md5']) || $md5 != $ret['md5']) { + $response = $this->uploadPart( + $data, + $partNumber, + $this->finishedEtags["uploadId"], + $encodedObjectName, + $md5 + ); + $ret = $response->json(); + } + + if (!$response->ok() || !isset($ret['md5']) || $md5 != $ret['md5']) { + return array(null, new Error($this->currentUrl, $response)); + } + $blockStatus = array('etag' => $ret['etag'], 'partNumber' => $partNumber); + array_push($this->finishedEtags['etags'], $blockStatus); + $partNumber += 1; + } else { + throw new \Exception("only support v1/v2 now!"); } - $blockStatus = array('etag' => $ret['etag'], 'partNumber' => $partNumber); - array_push($this->finishedEtags['etags'], $blockStatus); - $partNumber += 1; $uploaded += $blockSize; - $this->finishedEtags['uploaded'] = $uploaded; + if ($this->version == SplitUploadVersion::V2) { + $this->finishedEtags['uploaded'] = $uploaded; + } if ($this->resumeRecordFile !== null) { - $recordData = json_encode($this->finishedEtags); + if ($this->version == SplitUploadVersion::V1) { + $recordData = array( + 'contexts' => $this->contexts, + 'uploaded' => $uploaded + ); + $recordData = json_encode($recordData); + } elseif ($this->version == SplitUploadVersion::V2) { + $recordData = json_encode($this->finishedEtags); + } else { + throw new \Exception("only support v1/v2 now!"); + } if ($recordData) { $isWritten = file_put_contents($this->resumeRecordFile, $recordData); if ($isWritten === false) { @@ -377,15 +260,13 @@ final class ResumeUploader } } } - - list($ret, $err) = $this->completeParts($fname, $this->finishedEtags['uploadId'], $encodedObjectName); - if ($err !== null) { - $response = $err->getResponse(); - if ($isResumeUpload && $response->statusCode === 612) { - return $this->uploadV2($fname); - } + if ($this->version == SplitUploadVersion::V1) { + return $this->makeFile($fname); + } elseif ($this->version == SplitUploadVersion::V2) { + return $this->completeParts($fname, $this->finishedEtags['uploadId'], $encodedObjectName); + } else { + throw new \Exception("only support v1/v2 now!"); } - return array($ret, $err); } /** @@ -416,25 +297,15 @@ final class ResumeUploader /** * 创建文件 - * - * @param string $fname 文件名 - * @return array{array | null, Error | null} */ private function makeFile($fname) { $url = $this->fileUrl($fname); - $body = implode(',', array_map(function ($ctx) { - return $ctx['ctx']; - }, $this->contexts)); + $body = implode(',', $this->contexts); $response = $this->post($url, $body); if ($response->needRetry()) { $response = $this->post($url, $body); } - if ($response->statusCode === 200 || $response->statusCode === 701) { - if ($this->resumeRecordFile !== null) { - @unlink($this->resumeRecordFile); - } - } if (!$response->ok()) { return array(null, new Error($this->currentUrl, $response)); } @@ -445,7 +316,7 @@ final class ResumeUploader { $this->currentUrl = $url; $headers = array('Authorization' => 'UpToken ' . $this->upToken); - return Client::post($url, $data, $headers, $this->reqOpt); + return Client::post($url, $data, $headers); } private function blockSize($uploaded) @@ -458,15 +329,9 @@ final class ResumeUploader private function makeInitReq($encodedObjectName) { - list($ret, $err) = $this->initReq($encodedObjectName); - - if ($ret == null) { - return $err; - } - - $this->finishedEtags["uploadId"] = $ret['uploadId']; - $this->finishedEtags["expiredAt"] = $ret['expireAt']; - return $err; + $res = $this->initReq($encodedObjectName); + $this->finishedEtags["uploadId"] = $res['uploadId']; + $this->finishedEtags["expiredAt"] = $res['expireAt']; } /** @@ -474,18 +339,13 @@ final class ResumeUploader */ private function initReq($encodedObjectName) { - $url = $this->host . '/buckets/' . $this->bucket . '/objects/' . $encodedObjectName . '/uploads'; + $url = $this->host.'/buckets/'.$this->bucket.'/objects/'.$encodedObjectName.'/uploads'; $headers = array( 'Authorization' => 'UpToken ' . $this->upToken, 'Content-Type' => 'application/json' ); $response = $this->postWithHeaders($url, null, $headers); - $ret = $response->json(); - if ($response->ok() && $ret != null) { - return array($ret, null); - } - - return array(null, new Error($url, $response)); + return $response->json(); } /** @@ -498,29 +358,16 @@ final class ResumeUploader 'Content-Type' => 'application/octet-stream', 'Content-MD5' => $md5 ); - $url = $this->host . '/buckets/' . $this->bucket . '/objects/' . $encodedObjectName . - '/uploads/' . $uploadId . '/' . $partNumber; + $url = $this->host.'/buckets/'.$this->bucket.'/objects/'.$encodedObjectName. + '/uploads/'.$uploadId.'/'.$partNumber; $response = $this->put($url, $block, $headers); - if ($response->statusCode === 612) { - if ($this->resumeRecordFile !== null) { - @unlink($this->resumeRecordFile); - } - } return $response; } - /** - * 完成分片上传V2 - * - * @param string $fname 文件名 - * @param int $uploadId 由 {@see initReq} 获取 - * @param string $encodedObjectName 经过编码的存储路径 - * @return array{array | null, Error | null} - */ private function completeParts($fname, $uploadId, $encodedObjectName) { $headers = array( - 'Authorization' => 'UpToken ' . $this->upToken, + 'Authorization' => 'UpToken '.$this->upToken, 'Content-Type' => 'application/json' ); $etags = $this->finishedEtags['etags']; @@ -550,16 +397,11 @@ final class ResumeUploader 'parts' => $sortedEtags ); $jsonBody = json_encode($body); - $url = $this->host . '/buckets/' . $this->bucket . '/objects/' . $encodedObjectName . '/uploads/' . $uploadId; + $url = $this->host.'/buckets/'.$this->bucket.'/objects/'.$encodedObjectName.'/uploads/'.$uploadId; $response = $this->postWithHeaders($url, $jsonBody, $headers); if ($response->needRetry()) { $response = $this->postWithHeaders($url, $jsonBody, $headers); } - if ($response->statusCode === 200 || $response->statusCode === 612) { - if ($this->resumeRecordFile !== null) { - @unlink($this->resumeRecordFile); - } - } if (!$response->ok()) { return array(null, new Error($this->currentUrl, $response)); } @@ -569,12 +411,12 @@ final class ResumeUploader private function put($url, $data, $headers) { $this->currentUrl = $url; - return Client::put($url, $data, $headers, $this->reqOpt); + return Client::put($url, $data, $headers); } private function postWithHeaders($url, $data, $headers) { $this->currentUrl = $url; - return Client::post($url, $data, $headers, $this->reqOpt); + return Client::post($url, $data, $headers); } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/UploadManager.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/UploadManager.php index fcd11fad6..abadeb697 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/UploadManager.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Storage/UploadManager.php @@ -3,7 +3,6 @@ namespace Qiniu\Storage; use Qiniu\Config; use Qiniu\Http\HttpClient; -use Qiniu\Http\RequestOptions; use Qiniu\Storage\ResumeUploader; use Qiniu\Storage\FormUploader; @@ -15,40 +14,26 @@ use Qiniu\Storage\FormUploader; final class UploadManager { private $config; - /** - * @var RequestOptions - */ - private $reqOpt; - /** - * @param Config|null $config - * @param RequestOptions|null $reqOpt - */ - public function __construct(Config $config = null, RequestOptions $reqOpt = null) + public function __construct(Config $config = null) { if ($config === null) { $config = new Config(); } $this->config = $config; - - if ($reqOpt === null) { - $reqOpt = new RequestOptions(); - } - - $this->reqOpt = $reqOpt; } /** * 上传二进制流到七牛 * - * @param string $upToken 上传凭证 - * @param string $key 上传文件名 - * @param string $data 上传二进制流 - * @param array $params 自定义变量,规格参考 + * @param $upToken 上传凭证 + * @param $key 上传文件名 + * @param $data 上传二进制流 + * @param $params 自定义变量,规格参考 * http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar - * @param string $mime 上传数据的mimeType - * @param string $fname - * @param RequestOptions $reqOpt + * @param $mime 上传数据的mimeType + * @param $checkCrc 是否校验crc32 + * * @return array 包含已上传文件的信息,类似: * [ * "hash" => "", @@ -61,10 +46,8 @@ final class UploadManager $data, $params = null, $mime = 'application/octet-stream', - $fname = "default_filename", - $reqOpt = null + $fname = "default_filename" ) { - $reqOpt = $reqOpt === null ? $this->reqOpt : $reqOpt; $params = self::trimParams($params); return FormUploader::put( @@ -74,8 +57,7 @@ final class UploadManager $this->config, $params, $mime, - $fname, - $reqOpt + $fname ); } @@ -110,10 +92,8 @@ final class UploadManager $checkCrc = false, $resumeRecordFile = null, $version = 'v1', - $partSize = config::BLOCK_SIZE, - $reqOpt = null + $partSize = config::BLOCK_SIZE ) { - $reqOpt = $reqOpt === null ? $this->reqOpt : $reqOpt; $file = fopen($filePath, 'rb'); if ($file === false) { @@ -135,8 +115,7 @@ final class UploadManager $this->config, $params, $mime, - basename($filePath), - $reqOpt + basename($filePath) ); } @@ -150,8 +129,7 @@ final class UploadManager $this->config, $resumeRecordFile, $version, - $partSize, - $reqOpt + $partSize ); $ret = $up->upload(basename($filePath)); fclose($file); diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/Zone.php b/src/vendor/qiniu/php-sdk/src/Qiniu/Zone.php index 50d60c689..7af0e3f54 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/Zone.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/Zone.php @@ -20,11 +20,6 @@ class Zone extends Region return parent::regionHuanan(); } - public static function zoneCnEast2() - { - return parent::regionHuadong2(); - } - public static function zoneAs0() { return parent::regionSingapore(); @@ -45,14 +40,8 @@ class Zone extends Region return parent::qvmRegionHuabei(); } - public static function queryZone( - $ak, - $bucket, - $ucHost = null, - $backupUcHosts = array(), - $retryTimes = 2, - $reqOpt = null - ) { - return parent::queryRegion($ak, $bucket, $ucHost, $backupUcHosts, $retryTimes, $reqOpt); + public static function queryZone($ak, $bucket) + { + return parent::queryRegion($ak, $bucket); } } diff --git a/src/vendor/qiniu/php-sdk/src/Qiniu/functions.php b/src/vendor/qiniu/php-sdk/src/Qiniu/functions.php index cc258d7ec..6f87905f9 100644 --- a/src/vendor/qiniu/php-sdk/src/Qiniu/functions.php +++ b/src/vendor/qiniu/php-sdk/src/Qiniu/functions.php @@ -24,7 +24,7 @@ if (!defined('QINIU_FUNCTIONS_VERSION')) { /** * 计算输入流的crc32检验码 * - * @param $data string 待计算校验码的字符串 + * @param $data 待计算校验码的字符串 * * @return string 输入字符串的crc32校验码 */ @@ -129,27 +129,17 @@ if (!defined('QINIU_FUNCTIONS_VERSION')) { * @param string $key 待操作的文件名 * * @return string 符合七牛API规格的数据格式 - * @link https://developer.qiniu.com/kodo/api/data-format + * @link http://developer.qiniu.com/docs/v6/api/reference/data-formats.html */ - function entry($bucket, $key = null) + function entry($bucket, $key) { $en = $bucket; - if ($key !== null) { + if (!empty($key)) { $en = $bucket . ':' . $key; } return base64_urlSafeEncode($en); } - function decodeEntry($entry) - { - $en = base64_urlSafeDecode($entry); - $en = explode(':', $en); - if (count($en) == 1) { - return array($en[0], null); - } - return array($en[0], $en[1]); - } - /** * array 辅助方法,无值时不set * @@ -288,59 +278,4 @@ if (!defined('QINIU_FUNCTIONS_VERSION')) { $bucket = $scopeItems[0]; return array($accessKey, $bucket, null); } - - // polyfill ucwords for `php version < 5.4.32` or `5.5.0 <= php version < 5.5.16` - if (version_compare(phpversion(), "5.4.32") < 0 || - ( - version_compare(phpversion(), "5.5.0") >= 0 && - version_compare(phpversion(), "5.5.16") < 0 - ) - ) { - function ucwords($str, $delimiters = " \t\r\n\f\v") - { - $delims = preg_split('//u', $delimiters, -1, PREG_SPLIT_NO_EMPTY); - - foreach ($delims as $delim) { - $str = implode($delim, array_map('ucfirst', explode($delim, $str))); - } - - return $str; - } - } else { - function ucwords($str, $delimiters) - { - return \ucwords($str, $delimiters); - } - } - - /** - * 将 parse_url 的结果转换回字符串 - * TODO: add unit test - * - * @param $parsed_url - parse_url 的结果 - * @return string - */ - function unparse_url($parsed_url) - { - - $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; - - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; - - $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - - $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; - - $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; - - $pass = ($user || $pass) ? "$pass@" : ''; - - $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; - - $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; - - $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; - - return "$scheme$user$pass$host$port$path$query$fragment"; - } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/AuthTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/AuthTest.php index 99aec8589..8c6c531a7 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/AuthTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/AuthTest.php @@ -11,14 +11,12 @@ namespace Qiniu { } namespace Qiniu\Tests { - use PHPUnit\Framework\TestCase; - use Qiniu\Auth; use Qiniu\Http\Header; // @codingStandardsIgnoreEnd - class AuthTest extends TestCase + class AuthTest extends \PHPUnit_Framework_TestCase { public function testSign() @@ -67,230 +65,147 @@ namespace Qiniu\Tests { unset($_SERVER['override_qiniu_auth_time']); } + public function testVerifyCallback() + { + } + public function testSignQiniuAuthorization() { $auth = new Auth("ak", "sk"); - $testCases = array( - array( - "url" => "", - "method" => "", - "headers" => array( - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - "Content-Type" => array("application/x-www-form-urlencoded") - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:0i1vKClRDWFyNkcTFzwcE7PzX74=" - ), - array( - "url" => "", - "method" => "", - "headers" => array( - "Content-Type" => array("application/json") - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:K1DI0goT05yhGizDFE5FiPJxAj4=" - ), - array( - "url" => "", - "method" => "GET", - "headers" => array( - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - "Content-Type" => array("application/x-www-form-urlencoded"), - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:0i1vKClRDWFyNkcTFzwcE7PzX74=" - ), - array( - "url" => "", - "method" => "POST", - "headers" => array( - "Content-Type" => array("application/json"), - "X-Qiniu" => array("b"), - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:0ujEjW_vLRZxebsveBgqa3JyQ-w=" - ), - array( - "url" => "http://upload.qiniup.com", - "method" => "", - "headers" => array( - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - "Content-Type" => array("application/x-www-form-urlencoded"), - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:GShw5NitGmd5TLoo38nDkGUofRw=" - ), - array( - "url" => "http://upload.qiniup.com", - "method" => "", - "headers" => array( - "Content-Type" => array("application/json"), - "X-Qiniu-Bbb" => array("BBB", "AAA"), - "X-Qiniu-Aaa" => array("DDD", "CCC"), - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - ), - "body" => "{\"name\": \"test\"}", - "expectedToken" => "ak:DhNA1UCaBqSHCsQjMOLRfVn63GQ=" - ), - array( - "url" => "http://upload.qiniup.com", - "method" => "", - "headers" => array( - "Content-Type" => array("application/x-www-form-urlencoded"), - "X-Qiniu-Bbb" => array("BBB", "AAA"), - "X-Qiniu-Aaa" => array("DDD", "CCC"), - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - ), - "body" => "name=test&language=go", - "expectedToken" => "ak:KUAhrYh32P9bv0COD8ugZjDCmII=" - ), - array( - "url" => "http://upload.qiniup.com", - "method" => "", - "headers" => array( - "Content-Type" => array("application/x-www"), - "Content-Type" => array("application/x-www-form-urlencoded"), - "X-Qiniu-Bbb" => array("BBB", "AAA"), - "X-Qiniu-Aaa" => array("DDD", "CCC"), - ), - "body" => "name=test&language=go", - "expectedToken" => "ak:KUAhrYh32P9bv0COD8ugZjDCmII=" - ), - array( - "url" => "http://upload.qiniup.com/mkfile/sdf.jpg", - "method" => "", - "headers" => array( - "Content-Type" => array("application/x-www-form-urlencoded"), - "X-Qiniu-Bbb" => array("BBB", "AAA"), - "X-Qiniu-Aaa" => array("DDD", "CCC"), - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - ), - "body" => "name=test&language=go", - "expectedToken" => "ak:fkRck5_LeyfwdkyyLk-hyNwGKac=" - ), - array( - "url" => "http://upload.qiniup.com/mkfile/sdf.jpg?s=er3&df", - "method" => "", - "headers" => array( - "Content-Type" => array("application/x-www-form-urlencoded"), - "X-Qiniu-Bbb" => array("BBB", "AAA"), - "X-Qiniu-Aaa" => array("DDD", "CCC"), - "X-Qiniu-" => array("a"), - "X-Qiniu" => array("b"), - ), - "body" => "name=test&language=go", - "expectedToken" => "ak:PUFPWsEUIpk_dzUvvxTTmwhp3p4=" - ) - ); - - foreach ($testCases as $testCase) { - list($sign, $err) = $auth->signQiniuAuthorization( - $testCase["url"], - $testCase["method"], - $testCase["body"], - new Header($testCase["headers"]) - ); - - $this->assertNull($err); - $this->assertEquals($testCase["expectedToken"], $sign); - } - } - - public function testDisableQiniuTimestampSignatureDefault() - { - $auth = new Auth("ak", "sk"); - $authedHeaders = $auth->authorizationV2("https://example.com", "GET"); - $this->assertArrayHasKey("X-Qiniu-Date", $authedHeaders); - } - - public function testDisableQiniuTimestampSignature() - { - $auth = new Auth("ak", "sk", array( - "disableQiniuTimestampSignature" => true + // --- + $url = ""; + $method = ""; + $headers = new Header(array( + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + "Content-Type" => array("application/x-www-form-urlencoded"), )); - $authedHeaders = $auth->authorizationV2("https://example.com", "GET"); - $this->assertArrayNotHasKey("X-Qiniu-Date", $authedHeaders); - } - public function testDisableQiniuTimestampSignatureEnv() - { - putenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE=true"); - $auth = new Auth("ak", "sk"); - $authedHeaders = $auth->authorizationV2("https://example.com", "GET"); - $this->assertArrayNotHasKey("X-Qiniu-Date", $authedHeaders); - putenv('DISABLE_QINIU_TIMESTAMP_SIGNATURE'); - } - public function testDisableQiniuTimestampSignatureEnvBeIgnored() - { - putenv("DISABLE_QINIU_TIMESTAMP_SIGNATURE=true"); - $auth = new Auth("ak", "sk", array( - "disableQiniuTimestampSignature" => false + $body = "{\"name\": \"test\"}"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:0i1vKClRDWFyNkcTFzwcE7PzX74=", $sign); + + // --- + $url = ""; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/json"), )); - $authedHeaders = $auth->authorizationV2("https://example.com", "GET"); - $this->assertArrayHasKey("X-Qiniu-Date", $authedHeaders); - putenv('DISABLE_QINIU_TIMESTAMP_SIGNATURE'); - } - public function testQboxVerifyCallbackShouldOkWithRequiredOptions() - { - $auth = new Auth('abcdefghklmnopq', '1234567890'); - $ok = $auth->verifyCallback( - 'application/x-www-form-urlencoded', - 'QBox abcdefghklmnopq:T7F-SjxX7X2zI4Fc1vANiNt1AUE=', - 'https://test.qiniu.com/callback', - 'name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123' - ); - $this->assertTrue($ok); - } - public function testQboxVerifyCallbackShouldOkWithOmitOptions() - { - $auth = new Auth('abcdefghklmnopq', '1234567890'); - $ok = $auth->verifyCallback( - 'application/x-www-form-urlencoded', - 'QBox abcdefghklmnopq:T7F-SjxX7X2zI4Fc1vANiNt1AUE=', - 'https://test.qiniu.com/callback', - 'name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123', - 'POST', // this should be omit - array( - 'X-Qiniu-Bbb' => 'BBB' - ) // this should be omit - ); - $this->assertTrue($ok); - } - public function testQiniuVerifyCallbackShouldOk() - { - $auth = new Auth('abcdefghklmnopq', '1234567890'); - $ok = $auth->verifyCallback( - 'application/x-www-form-urlencoded', - 'Qiniu abcdefghklmnopq:ZqS7EZuAKrhZaEIxqNGxDJi41IQ=', - 'https://test.qiniu.com/callback', - 'name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123', - 'GET', - array( - 'X-Qiniu-Bbb' => 'BBB' - ) - ); - $this->assertTrue($ok); - } - public function testQiniuVerifyCallbackShouldFailed() - { - $auth = new Auth('abcdefghklmnopq', '1234567890'); - $ok = $auth->verifyCallback( - 'application/x-www-form-urlencoded', - 'Qiniu abcdefghklmnopq:ZqS7EZuAKrhZaEIxqNGxDJi41IQ=', - 'https://test.qiniu.com/callback', - 'name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123', - 'POST', - array( - 'X-Qiniu-Bbb' => 'BBB' - ) - ); - $this->assertFalse($ok); + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:K1DI0goT05yhGizDFE5FiPJxAj4=", $sign); + + // --- + $url = ""; + $method = "GET"; + $headers = new Header(array( + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + "Content-Type" => array("application/x-www-form-urlencoded"), + )); + $body = "{\"name\": \"test\"}"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:0i1vKClRDWFyNkcTFzwcE7PzX74=", $sign); + + // --- + $url = ""; + $method = "POST"; + $headers = new Header(array( + "Content-Type" => array("application/json"), + "X-Qiniu" => array("b"), + )); + $body = "{\"name\": \"test\"}"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:0ujEjW_vLRZxebsveBgqa3JyQ-w=", $sign); + + // --- + $url = "http://upload.qiniup.com"; + $method = ""; + $headers = new Header(array( + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + "Content-Type" => array("application/x-www-form-urlencoded"), + )); + $body = "{\"name\": \"test\"}"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:GShw5NitGmd5TLoo38nDkGUofRw=", $sign); + + // --- + $url = "http://upload.qiniup.com"; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/json"), + "X-Qiniu-Bbb" => array("BBB", "AAA"), + "X-Qiniu-Aaa" => array("DDD", "CCC"), + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + )); + $body = "{\"name\": \"test\"}"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:DhNA1UCaBqSHCsQjMOLRfVn63GQ=", $sign); + + // --- + $url = "http://upload.qiniup.com"; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/x-www-form-urlencoded"), + "X-Qiniu-Bbb" => array("BBB", "AAA"), + "X-Qiniu-Aaa" => array("DDD", "CCC"), + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + )); + $body = "name=test&language=go"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:KUAhrYh32P9bv0COD8ugZjDCmII=", $sign); + + // --- + $url = "http://upload.qiniup.com"; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/x-www"), + "Content-Type" => array("application/x-www-form-urlencoded"), + "X-Qiniu-Bbb" => array("BBB", "AAA"), + "X-Qiniu-Aaa" => array("DDD", "CCC"), + )); + $body = "name=test&language=go"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:KUAhrYh32P9bv0COD8ugZjDCmII=", $sign); + + // --- + $url = "http://upload.qiniup.com/mkfile/sdf.jpg"; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/x-www-form-urlencoded"), + "X-Qiniu-Bbb" => array("BBB", "AAA"), + "X-Qiniu-Aaa" => array("DDD", "CCC"), + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + )); + $body = "name=test&language=go"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:fkRck5_LeyfwdkyyLk-hyNwGKac=", $sign); + + $url = "http://upload.qiniup.com/mkfile/sdf.jpg?s=er3&df"; + $method = ""; + $headers = new Header(array( + "Content-Type" => array("application/x-www-form-urlencoded"), + "X-Qiniu-Bbb" => array("BBB", "AAA"), + "X-Qiniu-Aaa" => array("DDD", "CCC"), + "X-Qiniu-" => array("a"), + "X-Qiniu" => array("b"), + )); + $body = "name=test&language=go"; + list($sign, $err) = $auth->signQiniuAuthorization($url, $method, $body, $headers); + $this->assertNull($err); + $this->assertEquals("ak:PUFPWsEUIpk_dzUvvxTTmwhp3p4=", $sign); } } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Base64Test.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Base64Test.php index fed3da075..6d6335307 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Base64Test.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Base64Test.php @@ -1,11 +1,9 @@ bucketName = $bucketName; + $this->key = $key; + $this->key2 = $key2; global $customCallbackURL; - self::$customCallbackURL = $customCallbackURL; + $this->customCallbackURL = $customCallbackURL; global $testAuth; $config = new Config(); - self::$bucketManager = new BucketManager($testAuth, $config); + $this->bucketManager = new BucketManager($testAuth, $config); global $dummyAuth; - self::$dummyBucketManager = new BucketManager($dummyAuth); - - self::$bucketToCreate = 'phpsdk-ci-test' . rand(1, 1000); - - self::$bucketLifeRuleName = 'bucket_life_rule' . rand(1, 1000); - self::$bucketLifeRulePrefix = 'prefix-test' . rand(1, 1000); - - self::$bucketEventName = 'bucketevent' . rand(1, 1000); - self::$bucketEventPrefix = 'event-test' . rand(1, 1000); - - self::$keysToCleanup = array(); - } - - /** - * @afterClass - */ - public static function cleanupTestData() - { - $ops = BucketManager::buildBatchDelete(self::$bucketName, self::$keysToCleanup); - // ignore result for cleanup - self::$bucketManager->batch($ops); - } - - private static function getObjectKey($key) - { - $result = $key . rand(); - - self::$bucketManager->copy( - self::$bucketName, - $key, - self::$bucketName, - $result - ); - - self::$keysToCleanup[] = $result; - - return $result; + $this->dummyBucketManager = new BucketManager($dummyAuth); } public function testBuckets() { - list($list, $error) = self::$bucketManager->buckets(); + list($list, $error) = $this->bucketManager->buckets(); $this->assertNull($error); - $this->assertTrue(in_array(self::$bucketName, $list)); + $this->assertTrue(in_array($this->bucketName, $list)); - list($list2, $error) = self::$dummyBucketManager->buckets(); + list($list2, $error) = $this->dummyBucketManager->buckets(); $this->assertEquals(401, $error->code()); $this->assertNotNull($error->message()); $this->assertNotNull($error->getResponse()); $this->assertNull($list2); } - public function testListBuckets() + public function testListbuckets() { - list($ret, $error) = self::$bucketManager->listbuckets('z0'); + list($ret, $error) = $this->bucketManager->listbuckets('z0'); $this->assertNull($error); $this->assertNotNull($ret); } public function testCreateBucket() { - list($ret, $error) = self::$bucketManager->createBucket(self::$bucketToCreate); + list($ret, $error) = $this->bucketManager->createBucket('phpsdk-ci-test'); $this->assertNull($error); $this->assertNotNull($ret); } public function testDeleteBucket() { - list($ret, $error) = self::$bucketManager->deleteBucket(self::$bucketToCreate); + list($ret, $error) = $this->bucketManager->deleteBucket('phpsdk-ci-test'); $this->assertNull($error); $this->assertNotNull($ret); } public function testDomains() { - list($ret, $error) = self::$bucketManager->domains(self::$bucketName); + list($ret, $error) = $this->bucketManager->domains($this->bucketName); $this->assertNull($error); $this->assertNotNull($ret); } public function testBucketInfo() { - list($ret, $error) = self::$bucketManager->bucketInfo(self::$bucketName); + list($ret, $error) = $this->bucketManager->bucketInfo($this->bucketName); $this->assertNull($error); $this->assertNotNull($ret); } public function testBucketInfos() { - list($ret, $error) = self::$bucketManager->bucketInfos('z0'); + list($ret, $error) = $this->bucketManager->bucketInfos('z0'); $this->assertNull($error); $this->assertNotNull($ret); } public function testList() { - list($ret, $error) = self::$bucketManager->listFiles(self::$bucketName, null, null, 10); + list($ret, $error) = $this->bucketManager->listFiles($this->bucketName, null, null, 10); $this->assertNull($error); $this->assertNotNull($ret['items'][0]); $this->assertNotNull($ret['marker']); @@ -154,7 +100,7 @@ class BucketTest extends TestCase public function testListFilesv2() { - list($ret, $error) = self::$bucketManager->listFilesv2(self::$bucketName, null, null, 10); + list($ret, $error) = $this->bucketManager->listFilesv2($this->bucketName, null, null, 10); $this->assertNull($error); $this->assertNotNull($ret); } @@ -162,92 +108,85 @@ class BucketTest extends TestCase public function testBucketLifecycleRule() { // delete - self::$bucketManager->deleteBucketLifecycleRule(self::$bucketName, self::$bucketLifeRuleName); + $this->bucketManager->deleteBucketLifecycleRule($this->bucketName, 'demo'); // add - list($ret, $error) = self::$bucketManager->bucketLifecycleRule( - self::$bucketName, - self::$bucketLifeRuleName, - self::$bucketLifeRulePrefix, + list($ret, $error) = $this->bucketManager->bucketLifecycleRule( + $this->bucketName, + 'demo', + 'test', 80, 70, 72, - 74, - 71 + 74 ); $this->assertNull($error); $this->assertNotNull($ret); // get - list($ret, $error) = self::$bucketManager->getBucketLifecycleRules(self::$bucketName); + list($ret, $error) = $this->bucketManager->getBucketLifecycleRules($this->bucketName); $this->assertNull($error); $this->assertNotNull($ret); $rule = null; foreach ($ret as $r) { - if ($r["name"] === self::$bucketLifeRuleName) { + if ($r["name"] === "demo") { $rule = $r; break; } } $this->assertNotNull($rule); - $this->assertEquals(self::$bucketLifeRulePrefix, $rule["prefix"]); + $this->assertEquals("test", $rule["prefix"]); $this->assertEquals(80, $rule["delete_after_days"]); $this->assertEquals(70, $rule["to_line_after_days"]); - $this->assertEquals(71, $rule["to_archive_ir_after_days"]); $this->assertEquals(72, $rule["to_archive_after_days"]); $this->assertEquals(74, $rule["to_deep_archive_after_days"]); // update - list($ret, $error) = self::$bucketManager->updateBucketLifecycleRule( - self::$bucketName, - self::$bucketLifeRuleName, - 'update-' . self::$bucketLifeRulePrefix, + list($ret, $error) = $this->bucketManager->updateBucketLifecycleRule( + $this->bucketName, + 'demo', + 'testupdate', 90, 75, 80, - 85, - 78 + 85 ); $this->assertNull($error); $this->assertNotNull($ret); // get - list($ret, $error) = self::$bucketManager->getBucketLifecycleRules(self::$bucketName); + list($ret, $error) = $this->bucketManager->getBucketLifecycleRules($this->bucketName); $this->assertNull($error); $this->assertNotNull($ret); $rule = null; foreach ($ret as $r) { - if ($r["name"] === self::$bucketLifeRuleName) { + if ($r["name"] === "demo") { $rule = $r; break; } } $this->assertNotNull($rule); - $this->assertEquals('update-' . self::$bucketLifeRulePrefix, $rule["prefix"]); + $this->assertEquals("testupdate", $rule["prefix"]); $this->assertEquals(90, $rule["delete_after_days"]); $this->assertEquals(75, $rule["to_line_after_days"]); - $this->assertEquals(78, $rule["to_archive_ir_after_days"]); $this->assertEquals(80, $rule["to_archive_after_days"]); $this->assertEquals(85, $rule["to_deep_archive_after_days"]); // delete - list($ret, $error) = self::$bucketManager->deleteBucketLifecycleRule( - self::$bucketName, - self::$bucketLifeRuleName - ); + list($ret, $error) = $this->bucketManager->deleteBucketLifecycleRule($this->bucketName, 'demo'); $this->assertNull($error); $this->assertNotNull($ret); } public function testPutBucketEvent() { - list($ret, $error) = self::$bucketManager->putBucketEvent( - self::$bucketName, - self::$bucketEventName, - self::$bucketEventPrefix, + list($ret, $error) = $this->bucketManager->putBucketEvent( + $this->bucketName, + 'bucketevent', + 'test', 'img', array('copy'), - self::$customCallbackURL + $this->customCallbackURL ); $this->assertNull($error); $this->assertNotNull($ret); @@ -255,45 +194,45 @@ class BucketTest extends TestCase public function testUpdateBucketEvent() { - list($ret, $error) = self::$bucketManager->updateBucketEvent( - self::$bucketName, - self::$bucketEventName, - self::$bucketEventPrefix, + list($ret, $error) = $this->bucketManager->updateBucketEvent( + $this->bucketName, + 'bucketevent', + 'test', 'video', array('copy'), - self::$customCallbackURL + $this->customCallbackURL ); $this->assertNull($error); $this->assertNotNull($ret); } - public function testGetBucketEvents() + public function testGetBucketEvent() { - list($ret, $error) = self::$bucketManager->getBucketEvents(self::$bucketName); + list($ret, $error) = $this->bucketManager->getBucketEvents($this->bucketName); $this->assertNull($error); $this->assertNotNull($ret); } public function testDeleteBucketEvent() { - list($ret, $error) = self::$bucketManager->deleteBucketEvent(self::$bucketName, self::$bucketEventName); + list($ret, $error) = $this->bucketManager->deleteBucketEvent($this->bucketName, 'bucketevent'); $this->assertNull($error); $this->assertNotNull($ret); } public function testStat() { - list($stat, $error) = self::$bucketManager->stat(self::$bucketName, self::$key); + list($stat, $error) = $this->bucketManager->stat($this->bucketName, $this->key); $this->assertNull($error); $this->assertNotNull($stat); $this->assertNotNull($stat['hash']); - list($stat, $error) = self::$bucketManager->stat(self::$bucketName, 'nofile'); + list($stat, $error) = $this->bucketManager->stat($this->bucketName, 'nofile'); $this->assertEquals(612, $error->code()); $this->assertNotNull($error->message()); $this->assertNull($stat); - list($stat, $error) = self::$bucketManager->stat('nobucket', 'nofile'); + list($stat, $error) = $this->bucketManager->stat('nobucket', 'nofile'); $this->assertEquals(631, $error->code()); $this->assertNotNull($error->message()); $this->assertNull($stat); @@ -301,77 +240,79 @@ class BucketTest extends TestCase public function testDelete() { - $fileToDel = self::getObjectKey(self::$key); - list(, $error) = self::$bucketManager->delete(self::$bucketName, $fileToDel); - $this->assertNull($error); + list($ret, $error) = $this->bucketManager->delete($this->bucketName, 'del'); + $this->assertNotNull($error); + $this->assertNull($ret); } public function testRename() { - $fileToRename = self::getObjectKey(self::$key); - $fileRenamed = $fileToRename . 'new'; - list(, $error) = self::$bucketManager->rename(self::$bucketName, $fileToRename, $fileRenamed); + $key = 'renamefrom' . rand(); + $this->bucketManager->copy($this->bucketName, $this->key, $this->bucketName, $key); + $key2 = 'renameto' . $key; + list($ret, $error) = $this->bucketManager->rename($this->bucketName, $key, $key2); + $this->assertNull($error); + list($ret, $error) = $this->bucketManager->delete($this->bucketName, $key2); $this->assertNull($error); - self::$keysToCleanup[] = $fileRenamed; } public function testCopy() { - $fileToCopy = self::getObjectKey(self::$key2); - $fileCopied = $fileToCopy . 'copied'; + $key = 'copyto' . rand(); + $this->bucketManager->delete($this->bucketName, $key); + + list($ret, $error) = $this->bucketManager->copy( + $this->bucketName, + $this->key, + $this->bucketName, + $key + ); + $this->assertNull($error); //test force copy - list(, $error) = self::$bucketManager->copy( - self::$bucketName, - $fileToCopy, - self::$bucketName, - $fileCopied, + list($ret, $error) = $this->bucketManager->copy( + $this->bucketName, + $this->key2, + $this->bucketName, + $key, true ); $this->assertNull($error); - list($fileToCopyStat,) = self::$bucketManager->stat(self::$bucketName, $fileToCopy); - list($fileCopiedStat,) = self::$bucketManager->stat(self::$bucketName, $fileCopied); + list($key2Stat,) = $this->bucketManager->stat($this->bucketName, $this->key2); + list($key2CopiedStat,) = $this->bucketManager->stat($this->bucketName, $key); - $this->assertEquals($fileToCopyStat['hash'], $fileCopiedStat['hash']); + $this->assertEquals($key2Stat['hash'], $key2CopiedStat['hash']); - self::$keysToCleanup[] = $fileCopied; + list($ret, $error) = $this->bucketManager->delete($this->bucketName, $key); + $this->assertNull($error); } public function testChangeMime() { - $fileToChange = self::getObjectKey('php-sdk.html'); - list(, $error) = self::$bucketManager->changeMime( - self::$bucketName, - $fileToChange, - 'text/plain' + list($ret, $error) = $this->bucketManager->changeMime( + $this->bucketName, + 'php-sdk.html', + 'text/html' ); $this->assertNull($error); - - list($ret, $error) = self::$bucketManager->stat( - self::$bucketName, - $fileToChange - ); - $this->assertNull($error); - $this->assertEquals('text/plain', $ret['mimeType']); } public function testPrefetch() { - list($ret, $error) = self::$bucketManager->prefetch( - self::$bucketName, + list($ret, $error) = $this->bucketManager->prefetch( + $this->bucketName, 'php-sdk.html' ); $this->assertNull($error); - $this->assertNotNull($ret); } public function testPrefetchFailed() { - list($ret, $error) = self::$bucketManager->prefetch( + list($ret, $error) = $this->bucketManager->prefetch( 'fakebucket', 'php-sdk.html' ); @@ -381,25 +322,25 @@ class BucketTest extends TestCase public function testFetch() { - list($ret, $error) = self::$bucketManager->fetch( + list($ret, $error) = $this->bucketManager->fetch( 'http://developer.qiniu.com/docs/v6/sdk/php-sdk.html', - self::$bucketName, + $this->bucketName, 'fetch.html' ); $this->assertNull($error); $this->assertArrayHasKey('hash', $ret); - list($ret, $error) = self::$bucketManager->fetch( + list($ret, $error) = $this->bucketManager->fetch( 'http://developer.qiniu.com/docs/v6/sdk/php-sdk.html', - self::$bucketName, + $this->bucketName, '' ); $this->assertNull($error); $this->assertArrayHasKey('key', $ret); - list($ret, $error) = self::$bucketManager->fetch( + list($ret, $error) = $this->bucketManager->fetch( 'http://developer.qiniu.com/docs/v6/sdk/php-sdk.html', - self::$bucketName + $this->bucketName ); $this->assertNull($error); $this->assertArrayHasKey('key', $ret); @@ -407,7 +348,7 @@ class BucketTest extends TestCase public function testFetchFailed() { - list($ret, $error) = self::$bucketManager->fetch( + list($ret, $error) = $this->bucketManager->fetch( 'http://developer.qiniu.com/docs/v6/sdk/php-sdk.html', 'fakebucket' ); @@ -417,27 +358,27 @@ class BucketTest extends TestCase public function testAsynchFetch() { - list($ret, $error) = self::$bucketManager->asynchFetch( + list($ret, $error) = $this->bucketManager->asynchFetch( 'http://devtools.qiniu.com/qiniu.png', - self::$bucketName, + $this->bucketName, null, 'qiniu.png' ); $this->assertNull($error); $this->assertArrayHasKey('id', $ret); - list($ret, $error) = self::$bucketManager->asynchFetch( + list($ret, $error) = $this->bucketManager->asynchFetch( 'http://devtools.qiniu.com/qiniu.png', - self::$bucketName, + $this->bucketName, null, '' ); $this->assertNull($error); $this->assertArrayHasKey('id', $ret); - list($ret, $error) = self::$bucketManager->asynchFetch( + list($ret, $error) = $this->bucketManager->asynchFetch( 'http://devtools.qiniu.com/qiniu.png', - self::$bucketName + $this->bucketName ); $this->assertNull($error); $this->assertArrayHasKey('id', $ret); @@ -445,7 +386,7 @@ class BucketTest extends TestCase public function testAsynchFetchFailed() { - list($ret, $error) = self::$bucketManager->asynchFetch( + list($ret, $error) = $this->bucketManager->asynchFetch( 'http://devtools.qiniu.com/qiniu.png', 'fakebucket' ); @@ -458,229 +399,150 @@ class BucketTest extends TestCase { $key = 'copyto' . rand(); $ops = BucketManager::buildBatchCopy( - self::$bucketName, - array(self::$key => $key), - self::$bucketName, + $this->bucketName, + array($this->key => $key), + $this->bucketName, true ); - list($ret, $error) = self::$bucketManager->batch($ops); - $this->assertNull($error); + list($ret, $error) = $this->bucketManager->batch($ops); + $this->assertEquals(200, $ret[0]['code']); + $ops = BucketManager::buildBatchDelete($this->bucketName, array($key)); + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertEquals(200, $ret[0]['code']); - - self::$keysToCleanup[] = $key; } public function testBatchMove() { - $fileToMove = self::getObjectKey(self::$key); - $fileMoved = $fileToMove . 'to'; + $key = 'movefrom' . rand(); + $this->bucketManager->copy($this->bucketName, $this->key, $this->bucketName, $key); + $key2 = $key . 'to'; $ops = BucketManager::buildBatchMove( - self::$bucketName, - array($fileToMove => $fileMoved), - self::$bucketName, + $this->bucketName, + array($key => $key2), + $this->bucketName, true ); - list($ret, $error) = self::$bucketManager->batch($ops); - $this->assertNull($error); + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertEquals(200, $ret[0]['code']); - self::$keysToCleanup[] = $fileMoved; + list($ret, $error) = $this->bucketManager->delete($this->bucketName, $key2); + $this->assertNull($error); } public function testBatchRename() { - $fileToRename = self::getObjectKey(self::$key); - $fileRenamed = $fileToRename . 'to'; - - $ops = BucketManager::buildBatchRename( - self::$bucketName, - array($fileToRename => $fileRenamed), - true - ); - list($ret, $error) = self::$bucketManager->batch($ops); - $this->assertNull($error); + $key = 'rename' . rand(); + $this->bucketManager->copy($this->bucketName, $this->key, $this->bucketName, $key); + $key2 = $key . 'to'; + $ops = BucketManager::buildBatchRename($this->bucketName, array($key => $key2), true); + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertEquals(200, $ret[0]['code']); - - self::$keysToCleanup[] = $fileRenamed; + list($ret, $error) = $this->bucketManager->delete($this->bucketName, $key2); + $this->assertNull($error); } public function testBatchStat() { - $ops = BucketManager::buildBatchStat(self::$bucketName, array('php-sdk.html')); - list($ret, $error) = self::$bucketManager->batch($ops); - $this->assertNull($error); + $ops = BucketManager::buildBatchStat($this->bucketName, array('php-sdk.html')); + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertEquals(200, $ret[0]['code']); } public function testBatchChangeTypeAndBatchRestoreAr() { - $key = self::getObjectKey(self::$key); + $key = 'toChangeTypeThenRestore' . rand(); + $this->bucketManager->copy($this->bucketName, $this->key, $this->bucketName, $key); - $ops = BucketManager::buildBatchChangeType(self::$bucketName, array($key => 2)); // 2 Archive - list($ret, $error) = self::$bucketManager->batch($ops); + $ops = BucketManager::buildBatchChangeType($this->bucketName, array($key => 2)); // 2 Archive + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertNull($error); $this->assertEquals(200, $ret[0]['code']); - $ops = BucketManager::buildBatchRestoreAr(self::$bucketName, array($key => 1)); // 1 day - list($ret, $error) = self::$bucketManager->batch($ops); + $ops = BucketManager::buildBatchRestoreAr($this->bucketName, array($key => 1)); // 1 day + list($ret, $error) = $this->bucketManager->batch($ops); $this->assertNull($error); $this->assertEquals(200, $ret[0]['code']); + + $this->bucketManager->delete($this->bucketName, $key); } public function testDeleteAfterDays() { - $key = "noexist" . rand(); - list($ret, $error) = self::$bucketManager->deleteAfterDays(self::$bucketName, $key, 1); + $key = rand(); + list($ret, $error) = $this->bucketManager->deleteAfterDays($this->bucketName, $key, 1); $this->assertNotNull($error); - $this->assertNull($ret); - $key = self::getObjectKey(self::$key); - list(, $error) = self::$bucketManager->deleteAfterDays(self::$bucketName, $key, 1); - $this->assertNull($error); - - list($ret, $error) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($error); - $this->assertGreaterThan(23 * 3600, $ret['expiration'] - time()); - $this->assertLessThan(48 * 3600, $ret['expiration'] - time()); - } - - public function testSetObjectLifecycle() - { - $key = self::getObjectKey(self::$key); - - list(, $err) = self::$bucketManager->setObjectLifecycle( - self::$bucketName, - $key, - 10, - 20, - 30, - 40, - 15 - ); - $this->assertNull($err); - - list($ret, $error) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($error); - $this->assertNotNull($ret['transitionToIA']); - $this->assertNotNull($ret['transitionToArchiveIR']); - $this->assertNotNull($ret['transitionToARCHIVE']); - $this->assertNotNull($ret['transitionToDeepArchive']); - $this->assertNotNull($ret['expiration']); - } - - public function testSetObjectLifecycleWithCond() - { - $key = self::getObjectKey(self::$key); - - list($ret, $err) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($err); - $key_hash = $ret['hash']; - $key_fsize = $ret['fsize']; - - list(, $err) = self::$bucketManager->setObjectLifecycleWithCond( - self::$bucketName, - $key, - array( - 'hash' => $key_hash, - 'fsize' => $key_fsize - ), - 10, - 20, - 30, - 40, - 15 - ); - $this->assertNull($err); - - list($ret, $error) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($error); - $this->assertNotNull($ret['transitionToIA']); - $this->assertNotNull($ret['transitionToArchiveIR']); - $this->assertNotNull($ret['transitionToARCHIVE']); - $this->assertNotNull($ret['transitionToDeepArchive']); - $this->assertNotNull($ret['expiration']); - } - - public function testBatchSetObjectLifecycle() - { - $key = self::getObjectKey(self::$key); - - $ops = BucketManager::buildBatchSetObjectLifecycle( - self::$bucketName, - array($key), - 10, - 20, - 30, - 40, - 15 - ); - list($ret, $err) = self::$bucketManager->batch($ops); - $this->assertNull($err); - $this->assertEquals(200, $ret[0]['code']); + $this->bucketManager->copy($this->bucketName, $this->key, $this->bucketName, $key); + list($ret, $error) = $this->bucketManager->deleteAfterDays($this->bucketName, $key, 1); + $this->assertEquals(null, $ret); } public function testGetCorsRules() { - list(, $err) = self::$bucketManager->getCorsRules(self::$bucketName); + list($ret, $err) = $this->bucketManager->getCorsRules($this->bucketName); $this->assertNull($err); } public function testPutBucketAccessStyleMode() { - list(, $err) = self::$bucketManager->putBucketAccessStyleMode(self::$bucketName, 0); + list($ret, $err) = $this->bucketManager->putBucketAccessStyleMode($this->bucketName, 0); $this->assertNull($err); } public function testPutBucketAccessMode() { - list(, $err) = self::$bucketManager->putBucketAccessMode(self::$bucketName, 0); + list($ret, $err) = $this->bucketManager->putBucketAccessMode($this->bucketName, 0); $this->assertNull($err); } public function testPutReferAntiLeech() { - list(, $err) = self::$bucketManager->putReferAntiLeech(self::$bucketName, 0, "1", "*"); + list($ret, $err) = $this->bucketManager->putReferAntiLeech($this->bucketName, 0, "1", "*"); $this->assertNull($err); } public function testPutBucketMaxAge() { - list(, $err) = self::$bucketManager->putBucketMaxAge(self::$bucketName, 31536000); + list($ret, $err) = $this->bucketManager->putBucketMaxAge($this->bucketName, 31536000); $this->assertNull($err); } public function testPutBucketQuota() { - list(, $err) = self::$bucketManager->putBucketQuota(self::$bucketName, -1, -1); + list($ret, $err) = $this->bucketManager->putBucketQuota($this->bucketName, -1, -1); $this->assertNull($err); } public function testGetBucketQuota() { - list(, $err) = self::$bucketManager->getBucketQuota(self::$bucketName); + list($ret, $err) = $this->bucketManager->getBucketQuota($this->bucketName); $this->assertNull($err); } public function testChangeType() { - $fileToChange = self::getObjectKey(self::$key); - - list(, $err) = self::$bucketManager->changeType(self::$bucketName, $fileToChange, 0); + list($ret, $err) = $this->bucketManager->changeType($this->bucketName, $this->key, 0); $this->assertNull($err); - list(, $err) = self::$bucketManager->changeType(self::$bucketName, $fileToChange, 1); + list($ret, $err) = $this->bucketManager->changeType($this->bucketName, $this->key, 1); $this->assertNull($err); } public function testArchiveRestoreAr() { - $key = self::getObjectKey(self::$key); + $key = 'archiveToRestore' . rand(); + $this->bucketManager->delete($this->bucketName, $key); - self::$bucketManager->changeType(self::$bucketName, $key, 2); + $this->bucketManager->copy( + $this->bucketName, + $this->key, + $this->bucketName, + $key + ); + $this->bucketManager->changeType($this->bucketName, $key, 2); - list(, $err) = self::$bucketManager->restoreAr(self::$bucketName, $key, 2); + list(, $err) = $this->bucketManager->restoreAr($this->bucketName, $key, 2); $this->assertNull($err); - - list($ret, $err) = self::$bucketManager->stat(self::$bucketName, $key); + list($ret, $err) = $this->bucketManager->stat($this->bucketName, $key); $this->assertNull($err); $this->assertEquals(2, $ret["type"]); @@ -691,17 +553,26 @@ class BucketTest extends TestCase // 2 means be unfrozen; $this->assertNotNull($ret["restoreStatus"]); $this->assertContains($ret["restoreStatus"], array(1, 2)); + + $this->bucketManager->delete($this->bucketName, $key); } public function testDeepArchiveRestoreAr() { - $key = self::getObjectKey(self::$key); + $key = 'deepArchiveToRestore' . rand(); + $this->bucketManager->delete($this->bucketName, $key); - self::$bucketManager->changeType(self::$bucketName, $key, 3); + $this->bucketManager->copy( + $this->bucketName, + $this->key, + $this->bucketName, + $key + ); + $this->bucketManager->changeType($this->bucketName, $key, 3); - list(, $err) = self::$bucketManager->restoreAr(self::$bucketName, $key, 1); + list(, $err) = $this->bucketManager->restoreAr($this->bucketName, $key, 1); $this->assertNull($err); - list($ret, $err) = self::$bucketManager->stat(self::$bucketName, $key); + list($ret, $err) = $this->bucketManager->stat($this->bucketName, $key); $this->assertNull($err); $this->assertEquals(3, $ret["type"]); @@ -712,22 +583,16 @@ class BucketTest extends TestCase // 2 means be unfrozen; $this->assertNotNull($ret["restoreStatus"]); $this->assertContains($ret["restoreStatus"], array(1, 2)); + + $this->bucketManager->delete($this->bucketName, $key); } public function testChangeStatus() { - $key = self::getObjectKey(self::$key); + list($ret, $err) = $this->bucketManager->changeStatus($this->bucketName, $this->key, 1); + $this->assertNull($err); - list(, $err) = self::$bucketManager->changeStatus(self::$bucketName, $key, 1); + list($ret, $err) = $this->bucketManager->changeStatus($this->bucketName, $this->key, 0); $this->assertNull($err); - list($ret, $err) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($err); - $this->assertEquals(1, $ret['status']); - - list(, $err) = self::$bucketManager->changeStatus(self::$bucketName, $key, 0); - $this->assertNull($err); - list($ret, $err) = self::$bucketManager->stat(self::$bucketName, $key); - $this->assertNull($err); - $this->assertArrayNotHasKey('status', $ret); } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/CdnManagerTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/CdnManagerTest.php index baa9486c5..2994e832a 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/CdnManagerTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/CdnManagerTest.php @@ -8,12 +8,10 @@ namespace Qiniu\Tests; -use PHPUnit\Framework\TestCase; - use Qiniu\Cdn\CdnManager; use Qiniu\Http\Client; -class CdnManagerTest extends TestCase +class CdnManagerTest extends \PHPUnit_Framework_TestCase { protected $cdnManager; protected $encryptKey; @@ -26,10 +24,7 @@ class CdnManagerTest extends TestCase protected $customDomain; protected $customDomain2; - /** - * @before - */ - protected function setUpCdnManager() + protected function setUp() { global $testAuth; $this->cdnManager = new CdnManager($testAuth); diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ConfigTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ConfigTest.php index 3c39a5c2a..9f7a7ac8a 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ConfigTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ConfigTest.php @@ -1,20 +1,14 @@ accessKey = $accessKey; @@ -33,6 +27,7 @@ namespace Qiniu\Tests { $hasException = true; } $this->assertFalse($hasException); + $this->assertEquals('http://api.qiniu.com', $apiHost); } public function testGetApiHostErrored() @@ -46,73 +41,5 @@ namespace Qiniu\Tests { } $this->assertTrue($hasException); } - - public function testGetApiHostV2() - { - $conf = new Config(); - list($apiHost, $err) = $conf->getApiHostV2($this->accessKey, $this->bucketName); - $this->assertNull($err); - } - - public function testGetApiHostV2Errored() - { - $conf = new Config(); - list($apiHost, $err) = $conf->getApiHostV2($this->accessKey, "fakebucket"); - $this->assertNotNull($err->code()); - $this->assertEquals(631, $err->code()); - $this->assertNull($apiHost); - } - - public function testSetUcHost() - { - $conf = new Config(); - $this->assertEquals('http://' . Config::UC_HOST, $conf->getUcHost()); - $conf->setUcHost("uc.example.com"); - $this->assertEquals("http://uc.example.com", $conf->getUcHost()); - - $conf = new Config(); - $conf->useHTTPS = true; - $this->assertEquals('https://' . Config::UC_HOST, $conf->getUcHost()); - $conf->setUcHost("uc.example.com"); - $this->assertEquals("https://uc.example.com", $conf->getUcHost()); - } - - public function testGetRegionWithCustomDomain() - { - $conf = new Config(); - $conf->setQueryRegionHost( - "uc.qbox.me" - ); - list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName); - $this->assertNull($err); - } - - public function testGetRegionWithBackupDomains() - { - $conf = new Config(); - $conf->setQueryRegionHost( - "fake-uc.phpsdk.qiniu.com", - array( - "unavailable-uc.phpsdk.qiniu.com", - Config::UC_HOST // real uc - ) - ); - list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName); - $this->assertNull($err); - } - - public function testGetRegionWithUcAndBackupDomains() - { - $conf = new Config(); - $conf->setUcHost("fake-uc.phpsdk.qiniu.com"); - $conf->setBackupQueryRegionHosts( - array( - "unavailable-uc.phpsdk.qiniu.com", - Config::UC_HOST // real uc - ) - ); - list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName); - $this->assertNull($err); - } } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Crc32Test.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Crc32Test.php index 63e24fd9f..bfb36da87 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Crc32Test.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/Crc32Test.php @@ -1,11 +1,9 @@ bucketName = $bucketName; global $testAuth; - self::$auth = $testAuth; - self::$cfg = new Config(); - - self::$keysToCleanup = array(); - } - - /** - * @afterClass - */ - public static function cleanupTestData() - { - $bucketManager = new BucketManager(self::$auth); - $ops = BucketManager::buildBatchDelete(self::$bucketName, self::$keysToCleanup); - // ignore result for cleanup - $bucketManager->batch($ops); - } - - private static function getObjectKey($key) - { - $result = $key . rand(); - self::$keysToCleanup[] = $result; - return $result; + $this->auth = $testAuth; + $this->cfg = new Config(); } public function testData() { - $key = self::getObjectKey('formput'); - $token = self::$auth->uploadToken(self::$bucketName); - list($ret, $error) = FormUploader::put($token, $key, 'hello world', self::$cfg, null, 'text/plain', null); - $this->assertNull($error); - $this->assertNotNull($ret['hash']); - } - - public function testDataWithProxy() - { - $key = self::getObjectKey('formput'); - $token = self::$auth->uploadToken(self::$bucketName); - list($ret, $error) = FormUploader::put( - $token, - $key, - 'hello world', - self::$cfg, - null, - 'text/plain', - null, - $this->makeReqOpt() - ); + $token = $this->auth->uploadToken($this->bucketName); + list($ret, $error) = FormUploader::put($token, 'formput', 'hello world', $this->cfg, null, 'text/plain', null); $this->assertNull($error); $this->assertNotNull($ret['hash']); } public function testData2() { - $key = self::getObjectKey('formput'); $upManager = new UploadManager(); - $token = self::$auth->uploadToken(self::$bucketName); - list($ret, $error) = $upManager->put($token, $key, 'hello world', null, 'text/plain', null); - $this->assertNull($error); - $this->assertNotNull($ret['hash']); - } - - public function testData2WithProxy() - { - $key = self::getObjectKey('formput'); - $upManager = new UploadManager(); - $token = self::$auth->uploadToken(self::$bucketName); - list($ret, $error) = $upManager->put( - $token, - $key, - 'hello world', - null, - 'text/plain', - null, - $this->makeReqOpt() - ); + $token = $this->auth->uploadToken($this->bucketName); + list($ret, $error) = $upManager->put($token, 'formput', 'hello world', null, 'text/plain', null); $this->assertNull($error); $this->assertNotNull($ret['hash']); } public function testDataFailed() { - $key = self::getObjectKey('formput'); - $token = self::$auth->uploadToken('fakebucket'); - list($ret, $error) = FormUploader::put( - $token, - $key, - 'hello world', - self::$cfg, - null, - 'text/plain', - null - ); + $token = $this->auth->uploadToken('fakebucket'); + list($ret, $error) = FormUploader::put($token, 'formput', 'hello world', $this->cfg, null, 'text/plain', null); $this->assertNull($ret); $this->assertNotNull($error); } public function testFile() { - $key = self::getObjectKey('formPutFile'); - $token = self::$auth->uploadToken(self::$bucketName, $key); - list($ret, $error) = FormUploader::putFile( - $token, - $key, - __file__, - self::$cfg, - null, - 'text/plain', - null - ); - $this->assertNull($error); - $this->assertNotNull($ret['hash']); - } - - public function testFileWithProxy() - { - $key = self::getObjectKey('formPutFile'); - $token = self::$auth->uploadToken(self::$bucketName, $key); - list($ret, $error) = FormUploader::putFile( - $token, - $key, - __file__, - self::$cfg, - null, - 'text/plain', - $this->makeReqOpt() - ); + $key = 'formPutFile'; + $token = $this->auth->uploadToken($this->bucketName, $key); + list($ret, $error) = FormUploader::putFile($token, $key, __file__, $this->cfg, null, 'text/plain', null); $this->assertNull($error); $this->assertNotNull($ret['hash']); } public function testFile2() { - $key = self::getObjectKey('formPutFile'); - $token = self::$auth->uploadToken(self::$bucketName, $key); + $key = 'formPutFile'; + $token = $this->auth->uploadToken($this->bucketName, $key); $upManager = new UploadManager(); list($ret, $error) = $upManager->putFile($token, $key, __file__, null, 'text/plain', null); $this->assertNull($error); $this->assertNotNull($ret['hash']); } - public function testFile2WithProxy() - { - $key = self::getObjectKey('formPutFile'); - $token = self::$auth->uploadToken(self::$bucketName, $key); - $upManager = new UploadManager(); - list($ret, $error) = $upManager->putFile( - $token, - $key, - __file__, - null, - 'text/plain', - false, - null, - 'v1', - Config::BLOCK_SIZE, - $this->makeReqOpt() - ); - $this->assertNull($error); - $this->assertNotNull($ret['hash']); - } - public function testFileFailed() { - $key = self::getObjectKey('fakekey'); - $token = self::$auth->uploadToken('fakebucket', $key); - list($ret, $error) = FormUploader::putFile($token, $key, __file__, self::$cfg, null, 'text/plain', null); + $key = 'fakekey'; + $token = $this->auth->uploadToken('fakebucket', $key); + list($ret, $error) = FormUploader::putFile($token, $key, __file__, $this->cfg, null, 'text/plain', null); $this->assertNull($ret); $this->assertNotNull($error); } - - private function makeReqOpt() - { - $reqOpt = new RequestOptions(); - $reqOpt->proxy = 'socks5://127.0.0.1:8080'; - $reqOpt->proxy_user_password = 'user:pass'; - return $reqOpt; - } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HeaderTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HeaderTest.php index 28af5f3d3..b7ecd1f96 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HeaderTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HeaderTest.php @@ -1,11 +1,9 @@ array('200'), @@ -147,21 +145,6 @@ class HeaderTest extends TestCase $this->assertFalse($hasException); } - public function testEmptyHeaderIterator() - { - $emptyHeader = new Header(); - - $hasException = false; - try { - foreach ($emptyHeader as $k => $v) { - $hasException = !isset($header[$k]); - } - } catch (\Exception $e) { - $hasException = true; - } - $this->assertFalse($hasException); - } - public function testCount() { $header = new Header($this->heads); diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HttpTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HttpTest.php index c122f8e5f..558bc1f11 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HttpTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/HttpTest.php @@ -1,18 +1,14 @@ assertEquals(200, $response->statusCode); + $this->assertEquals($response->statusCode, 200); $this->assertNotNull($response->body); $this->assertNull($response->error); } @@ -27,27 +23,10 @@ class HttpTest extends TestCase $this->assertNotNull($response->error); } - public function testGetTimeout() - { - $reqOpt = new RequestOptions(); - $reqOpt->timeout = 1; - $response = Client::get('localhost:9000/timeout.php', array(), $reqOpt); - $this->assertEquals(-1, $response->statusCode); - } - - public function testGetRedirect() - { - $response = Client::get('localhost:9000/redirect.php'); - $this->assertEquals(200, $response->statusCode); - $this->assertEquals('application/json;charset=UTF-8', $response->normalizedHeaders['Content-Type']); - $respData = $response->json(); - $this->assertEquals('ok', $respData['msg']); - } - public function testDelete() { $response = Client::delete('uc.qbox.me/bucketTagging', array()); - $this->assertEquals(401, $response->statusCode); + $this->assertEquals($response->statusCode, 401); $this->assertNotNull($response->body); $this->assertNotNull($response->error); } @@ -62,19 +41,10 @@ class HttpTest extends TestCase $this->assertNotNull($response->error); } - public function testDeleteTimeout() - { - $reqOpt = new RequestOptions(); - $reqOpt->timeout = 1; - $response = Client::delete('localhost:9000/timeout.php', array(), $reqOpt); - $this->assertEquals(-1, $response->statusCode); - } - - public function testPost() { $response = Client::post('qiniu.com', null); - $this->assertEquals(200, $response->statusCode); + $this->assertEquals($response->statusCode, 200); $this->assertNotNull($response->body); $this->assertNull($response->error); } @@ -82,37 +52,17 @@ class HttpTest extends TestCase public function testPostQiniu() { $response = Client::post('upload.qiniu.com', null); - $this->assertEquals(400, $response->statusCode); + $this->assertEquals($response->statusCode, 400); $this->assertNotNull($response->body); $this->assertNotNull($response->xReqId()); $this->assertNotNull($response->xLog()); $this->assertNotNull($response->error); } - public function testPostTimeout() - { - $reqOpt = new RequestOptions(); - $reqOpt->timeout = 1; - $response = Client::post('localhost:9000/timeout.php', null, array(), $reqOpt); - $this->assertEquals(-1, $response->statusCode); - } - - public function testSocks5Proxy() - { - $reqOpt = new RequestOptions(); - $reqOpt->proxy = 'socks5://localhost:8080'; - $response = Client::post('qiniu.com', null, array(), $reqOpt); - $this->assertEquals(-1, $response->statusCode); - - $reqOpt->proxy_user_password = 'user:pass'; - $response = Client::post('qiniu.com', null, array(), $reqOpt); - $this->assertEquals(200, $response->statusCode); - } - public function testPut() { $response = Client::PUT('uc.qbox.me/bucketTagging', null); - $this->assertEquals(401, $response->statusCode); + $this->assertEquals($response->statusCode, 401); $this->assertNotNull($response->body); $this->assertNotNull($response->error); } @@ -126,38 +76,4 @@ class HttpTest extends TestCase $this->assertNotNull($response->xLog()); $this->assertNotNull($response->error); } - - - public function testPutTimeout() - { - $reqOpt = new RequestOptions(); - $reqOpt->timeout = 1; - $response = Client::put('localhost:9000/timeout.php', null, array(), $reqOpt); - $this->assertEquals(-1, $response->statusCode); - } - - public function testNeedRetry() - { - $testCases = array_merge( - array(array(-1, true)), - array_map(function ($i) { - return array($i, false); - }, range(100, 499)), - array_map(function ($i) { - if (in_array($i, array( - 501, 509, 573, 579, 608, 612, 614, 616, 618, 630, 631, 632, 640, 701 - ))) { - return array($i, false); - } - return array($i, true); - }, range(500, 799)) - ); - $resp = new Response(-1, 222, array(), '{"msg": "mock"}', null); - foreach ($testCases as $testCase) { - list($code, $expectNeedRetry) = $testCase; - $resp->statusCode = $code; - $msg = $resp->statusCode . ' need' . ($expectNeedRetry ? '' : ' NOT') . ' retry'; - $this->assertEquals($expectNeedRetry, $resp->needRetry(), $msg); - } - } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ImageUrlBuilderTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ImageUrlBuilderTest.php index 486323cb3..fca87b6fe 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ImageUrlBuilderTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ImageUrlBuilderTest.php @@ -2,8 +2,6 @@ namespace Qiniu\Tests; -use PHPUnit\Framework\TestCase; - /** * imageprocess test * @@ -11,7 +9,7 @@ use PHPUnit\Framework\TestCase; * @subpackage test * @author Sherlock Ren */ -class ImageUrlBuilderTest extends TestCase +class ImageUrlBuilderTest extends \PHPUnit_Framework_TestCase { /** * 缩略图测试 diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/PfopTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/PfopTest.php index 77d06ecb5..d03b3f6e9 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/PfopTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/PfopTest.php @@ -1,49 +1,17 @@ execute($bucket, $key, $fops); @@ -54,7 +22,7 @@ class PfopTest extends TestCase } - public function testPfopExecuteAndStatusWithMultipleFops() + public function testPfops() { global $testAuth; $bucket = 'testres'; @@ -63,7 +31,7 @@ class PfopTest extends TestCase 'avthumb/m3u8/segtime/10/vcodec/libx264/s/320x240', 'vframe/jpg/offset/7/w/480/h/360', ); - $pfop = new PersistentFop($testAuth, self::getConfig()); + $pfop = new PersistentFop($testAuth, null); list($id, $error) = $pfop->execute($bucket, $key, $fops); $this->assertNull($error); @@ -73,218 +41,12 @@ class PfopTest extends TestCase $this->assertNull($error); } - private function pfopOptionsTestData() - { - return array( - array( - 'type' => null - ), - array( - 'type' => -1 - ), - array( - 'type' => 0 - ), - array( - 'type' => 1 - ), - array( - 'type' => 2 - ), - array( - 'workflowTemplateID' => 'test-workflow' - ) - ); - } - - public function testPfopExecuteWithOptions() - { - $bucket = self::$bucketName; - $key = 'qiniu.png'; - $pfop = new PersistentFop(self::$testAuth, self::getConfig()); - - $testCases = $this->pfopOptionsTestData(); - - foreach ($testCases as $testCase) { - $workflowTemplateID = null; - $type = null; - - if (array_key_exists('workflowTemplateID', $testCase)) { - $workflowTemplateID = $testCase['workflowTemplateID']; - } - if (array_key_exists('type', $testCase)) { - $type = $testCase['type']; - } - - if ($workflowTemplateID) { - $fops = null; - } else { - $persistentEntry = \Qiniu\entry( - $bucket, - implode( - '_', - array( - 'test-pfop/test-pfop-by-api', - 'type', - $type - ) - ) - ); - $fops = 'avinfo|saveas/' . $persistentEntry; - } - list($id, $error) = $pfop->execute( - $bucket, - $key, - $fops, - null, - null, - false, - $type, - $workflowTemplateID - ); - - if (in_array($type, array(null, 0, 1))) { - $this->assertNull($error); - list($status, $error) = $pfop->status($id); - $this->assertNotNull($status); - $this->assertNull($error); - if ($type == 1) { - $this->assertEquals(1, $status['type']); - } - if ($workflowTemplateID) { - // assertStringContainsString when PHPUnit >= 8.0 - $this->assertTrue( - strpos( - $status['taskFrom'], - $workflowTemplateID - ) !== false - ); - } - $this->assertNotEmpty($status['creationDate']); - } else { - $this->assertNotNull($error); - } - } - } - - public function testPfopWithInvalidArgument() - { - $bucket = self::$bucketName; - $key = 'qiniu.png'; - $pfop = new PersistentFop(self::$testAuth, self::getConfig()); - $err = null; - try { - $pfop->execute( - $bucket, - $key - ); - } catch (\Exception $e) { - $err = $e; - } - - $this->assertNotEmpty($err); - $this->assertTrue( - strpos( - $err->getMessage(), - 'Must provide one of fops or template_id' - ) !== false - ); - } - - public function testPfopWithUploadPolicy() - { - $bucket = self::$bucketName; - $testAuth = self::$testAuth; - $key = 'test-pfop/upload-file'; - - $testCases = $this->pfopOptionsTestData(); - - foreach ($testCases as $testCase) { - $workflowTemplateID = null; - $type = null; - - if (array_key_exists('workflowTemplateID', $testCase)) { - $workflowTemplateID = $testCase['workflowTemplateID']; - } - if (array_key_exists('type', $testCase)) { - $type = $testCase['type']; - } - - $putPolicy = array( - 'persistentType' => $type - ); - if ($workflowTemplateID) { - $putPolicy['persistentWorkflowTemplateID'] = $workflowTemplateID; - } else { - $persistentEntry = \Qiniu\entry( - $bucket, - implode( - '_', - array( - 'test-pfop/test-pfop-by-upload', - 'type', - $type - ) - ) - ); - $putPolicy['persistentOps'] = 'avinfo|saveas/' . $persistentEntry; - } - - if ($type == null) { - unset($putPolicy['persistentType']); - } - - $token = $testAuth->uploadToken( - $bucket, - $key, - 3600, - $putPolicy - ); - $upManager = new UploadManager(self::getConfig()); - list($ret, $error) = $upManager->putFile( - $token, - $key, - __file__, - null, - 'text/plain', - true - ); - - if (in_array($type, array(null, 0, 1))) { - $this->assertNull($error); - $this->assertNotEmpty($ret['persistentId']); - $id = $ret['persistentId']; - } else { - $this->assertNotNull($error); - return; - } - - $pfop = new PersistentFop($testAuth, self::getConfig()); - list($status, $error) = $pfop->status($id); - - $this->assertNotNull($status); - $this->assertNull($error); - if ($type == 1) { - $this->assertEquals(1, $status['type']); - } - if ($workflowTemplateID) { - // assertStringContainsString when PHPUnit >= 8.0 - $this->assertTrue( - strpos( - $status['taskFrom'], - $workflowTemplateID - ) !== false - ); - } - $this->assertNotEmpty($status['creationDate']); - } - } - public function testMkzip() { - $bucket = self::$bucketName; + global $testAuth; + $bucket = 'phpsdk'; $key = 'php-logo.png'; - $pfop = new PersistentFop(self::$testAuth, null); + $pfop = new PersistentFop($testAuth, null); $url1 = 'http://phpsdk.qiniudn.com/php-logo.png'; $url2 = 'http://phpsdk.qiniudn.com/php-sdk.html'; diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ResumeUpTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ResumeUpTest.php index 6feee55db..989786a43 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ResumeUpTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ResumeUpTest.php @@ -1,58 +1,47 @@ delete($bucketName, $key); + } + } + protected $bucketName; + protected $auth; + + protected function setUp() + { + global $bucketName; + $this->bucketName = $bucketName; global $testAuth; - self::$auth = $testAuth; - } - - - /** - * @afterClass - */ - public static function cleanupTestData() - { - $ops = BucketManager::buildBatchDelete(self::$bucketName, self::$keysToCleanup); - - $bucketManager = new BucketManager(self::$auth); - $bucketManager->batch($ops); - } - - private static function getObjectKey($key) - { - $result = $key . rand(); - self::$keysToCleanup[] = $result; - return $result; + $this->auth = $testAuth; } public function test4ML() { - $key = self::getObjectKey('resumePutFile4ML_'); + $key = "resumePutFile4ML_".rand(); $upManager = new UploadManager(); - $token = self::$auth->uploadToken(self::$bucketName, $key); + $token = $this->auth->uploadToken($this->bucketName, $key); $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -67,6 +56,7 @@ class ResumeUpTest extends TestCase ); $this->assertNull($error); $this->assertNotNull($ret['hash']); + unlink($resumeFile); $domain = getenv('QINIU_TEST_DOMAIN'); $response = Client::get("http://$domain/$key"); @@ -77,10 +67,11 @@ class ResumeUpTest extends TestCase public function test4ML2() { - $key = self::getObjectKey('resumePutFile4ML_'); - $cfg = new Config(); + $key = 'resumePutFile4ML_'.rand(); + $zone = new Zone(array('upload.fake.qiniu.com'), array('upload.qiniup.com')); + $cfg = new Config($zone); $upManager = new UploadManager($cfg); - $token = self::$auth->uploadToken(self::$bucketName, $key); + $token = $this->auth->uploadToken($this->bucketName, $key); $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -95,37 +86,7 @@ class ResumeUpTest extends TestCase ); $this->assertNull($error); $this->assertNotNull($ret['hash']); - - $domain = getenv('QINIU_TEST_DOMAIN'); - $response = Client::get("http://$domain/$key"); - $this->assertEquals(200, $response->statusCode); - $this->assertEquals(md5_file($tempFile, true), md5($response->body(), true)); - unlink($tempFile); - } - - public function test4ML2WithProxy() - { - $key = self::getObjectKey('resumePutFile4ML_'); - $cfg = new Config(); - $upManager = new UploadManager($cfg); - $token = self::$auth->uploadToken(self::$bucketName, $key); - $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); - $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); - $this->assertNotFalse($resumeFile); - list($ret, $error) = $upManager->putFile( - $token, - $key, - $tempFile, - null, - 'application/octet-stream', - false, - $resumeFile, - 'v2', - Config::BLOCK_SIZE, - $this->makeReqOpt() - ); - $this->assertNull($error); - $this->assertNotNull($ret['hash']); + unlink($resumeFile); $domain = getenv('QINIU_TEST_DOMAIN'); $response = Client::get("http://$domain/$key"); @@ -138,7 +99,7 @@ class ResumeUpTest extends TestCase // { // $key = 'resumePutFile8M'; // $upManager = new UploadManager(); - // $token = self::$auth->uploadToken(self::$bucketName, $key); + // $token = $this->auth->uploadToken($this->bucketName, $key); // $tempFile = qiniuTempFile(8*1024*1024+10); // list($ret, $error) = $upManager->putFile($token, $key, $tempFile); // $this->assertNull($error); @@ -149,7 +110,7 @@ class ResumeUpTest extends TestCase public function testFileWithFileType() { $config = new Config(); - $bucketManager = new BucketManager(self::$auth, $config); + $bucketManager = new BucketManager($this->auth, $config); $testCases = array( array( @@ -167,16 +128,17 @@ class ResumeUpTest extends TestCase ); foreach ($testCases as $testCase) { - $key = self::getObjectKey('FileType' . $testCase["name"]); + $key = 'FileType'.$testCase["name"].rand(); $police = array( "fileType" => $testCase["fileType"], ); - $token = self::$auth->uploadToken(self::$bucketName, $key, 3600, $police); + $token = $this->auth->uploadToken($this->bucketName, $key, 3600, $police); $upManager = new UploadManager(); list($ret, $error) = $upManager->putFile($token, $key, __file__, null, 'text/plain'); $this->assertNull($error); $this->assertNotNull($ret); - list($ret, $err) = $bucketManager->stat(self::$bucketName, $key); + array_push(self::$keyToDelete, $key); + list($ret, $err) = $bucketManager->stat($this->bucketName, $key); $this->assertNull($err); $this->assertEquals($testCase["fileType"], $ret["type"]); } @@ -184,10 +146,10 @@ class ResumeUpTest extends TestCase public function testResumeUploadWithParams() { - $key = self::getObjectKey('resumePutFile4ML_'); + $key = "resumePutFile4ML_".rand(); $upManager = new UploadManager(); $policy = array('returnBody' => '{"hash":$(etag),"fname":$(fname),"var_1":$(x:var_1),"var_2":$(x:var_2)}'); - $token = self::$auth->uploadToken(self::$bucketName, $key, 3600, $policy); + $token = $this->auth->uploadToken($this->bucketName, $key, 3600, $policy); $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -195,7 +157,7 @@ class ResumeUpTest extends TestCase $token, $key, $tempFile, - array("x:var_1" => "val_1", "x:var_2" => "val_2", "x-qn-meta-m1" => "val_1", "x-qn-meta-m2" => "val_2"), + ["x:var_1" => "val_1", "x:var_2" => "val_2", "x-qn-meta-m1" => "val_1", "x-qn-meta-m2" => "val_2"], 'application/octet-stream', false, $resumeFile @@ -205,20 +167,21 @@ class ResumeUpTest extends TestCase $this->assertEquals("val_1", $ret['var_1']); $this->assertEquals("val_2", $ret['var_2']); $this->assertEquals(basename($tempFile), $ret['fname']); + unlink($resumeFile); $domain = getenv('QINIU_TEST_DOMAIN'); $response = Client::get("http://$domain/$key"); $this->assertEquals(200, $response->statusCode); $this->assertEquals(md5_file($tempFile, true), md5($response->body(), true)); - $headers = $response->headers(); - $this->assertEquals("val_1", $headers["X-Qn-Meta-M1"]); - $this->assertEquals("val_2", $headers["X-Qn-Meta-M2"]); + $this->assertEquals("val_1", $response->headers()["X-Qn-Meta-M1"]); + $this->assertEquals("val_2", $response->headers()["X-Qn-Meta-M2"]); unlink($tempFile); } public function testResumeUploadV2() { - $cfg = new Config(); + $zone = new Zone(array('up.qiniup.com')); + $cfg = new Config($zone); $upManager = new UploadManager($cfg); $testFileSize = array( config::BLOCK_SIZE / 2, @@ -229,8 +192,8 @@ class ResumeUpTest extends TestCase ); $partSize = 5 * 1024 * 1024; foreach ($testFileSize as $item) { - $key = self::getObjectKey('resumePutFile4ML_'); - $token = self::$auth->uploadToken(self::$bucketName, $key); + $key = 'resumePutFile4ML_'.rand()."_"; + $token = $this->auth->uploadToken($this->bucketName, $key); $tempFile = qiniuTempFile($item); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -247,6 +210,7 @@ class ResumeUpTest extends TestCase ); $this->assertNull($error); $this->assertNotNull($ret['hash']); + unlink($resumeFile); $domain = getenv('QINIU_TEST_DOMAIN'); $response = Client::get("http://$domain/$key"); @@ -258,10 +222,10 @@ class ResumeUpTest extends TestCase public function testResumeUploadV2WithParams() { - $key = self::getObjectKey('resumePutFile4ML_'); + $key = "resumePutFile4ML_".rand(); $upManager = new UploadManager(); $policy = array('returnBody' => '{"hash":$(etag),"fname":$(fname),"var_1":$(x:var_1),"var_2":$(x:var_2)}'); - $token = self::$auth->uploadToken(self::$bucketName, $key, 3600, $policy); + $token = $this->auth->uploadToken($this->bucketName, $key, 3600, $policy); $tempFile = qiniuTempFile(4 * 1024 * 1024 + 10); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -269,7 +233,7 @@ class ResumeUpTest extends TestCase $token, $key, $tempFile, - array("x:var_1" => "val_1", "x:var_2" => "val_2", "x-qn-meta-m1" => "val_1", "x-qn-meta-m2" => "val_2"), + ["x:var_1" => "val_1", "x:var_2" => "val_2", "x-qn-meta-m1" => "val_1", "x-qn-meta-m2" => "val_2"], 'application/octet-stream', false, $resumeFile, @@ -280,14 +244,14 @@ class ResumeUpTest extends TestCase $this->assertEquals("val_1", $ret['var_1']); $this->assertEquals("val_2", $ret['var_2']); $this->assertEquals(basename($tempFile), $ret['fname']); + unlink($resumeFile); $domain = getenv('QINIU_TEST_DOMAIN'); $response = Client::get("http://$domain/$key"); $this->assertEquals(200, $response->statusCode); $this->assertEquals(md5_file($tempFile, true), md5($response->body(), true)); - $headers = $response->headers(); - $this->assertEquals("val_1", $headers["X-Qn-Meta-M1"]); - $this->assertEquals("val_2", $headers["X-Qn-Meta-M2"]); + $this->assertEquals("val_1", $response->headers()["X-Qn-Meta-M1"]); + $this->assertEquals("val_2", $response->headers()["X-Qn-Meta-M2"]); unlink($tempFile); } @@ -296,7 +260,8 @@ class ResumeUpTest extends TestCase // but not match the test style of this project public function testResumeUploadWithInvalidVersion() { - $cfg = new Config(); + $zone = new Zone(array('up.qiniup.com')); + $cfg = new Config($zone); $upManager = new UploadManager($cfg); $testFileSize = config::BLOCK_SIZE * 2; $partSize = 5 * 1024 * 1024; @@ -309,8 +274,8 @@ class ResumeUpTest extends TestCase $expectExceptionCount = 0; foreach ($testInvalidVersions as $invalidVersion) { - $key = self::getObjectKey('resumePutFile4ML_'); - $token = self::$auth->uploadToken(self::$bucketName, $key); + $key = 'resumePutFile4ML_'.rand()."_"; + $token = $this->auth->uploadToken($this->bucketName, $key); $tempFile = qiniuTempFile($testFileSize); $resumeFile = tempnam(sys_get_temp_dir(), 'resume_file'); $this->assertNotFalse($resumeFile); @@ -339,16 +304,9 @@ class ResumeUpTest extends TestCase $this->assertTrue($isRightException); } + unlink($resumeFile); unlink($tempFile); } $this->assertEquals(count($testInvalidVersions), $expectExceptionCount); } - - private function makeReqOpt() - { - $reqOpt = new RequestOptions(); - $reqOpt->proxy = 'socks5://127.0.0.1:8080'; - $reqOpt->proxy_user_password = 'user:pass'; - return $reqOpt; - } } diff --git a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ZoneTest.php b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ZoneTest.php index fbab5284e..cc5cce507 100644 --- a/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ZoneTest.php +++ b/src/vendor/qiniu/php-sdk/tests/Qiniu/Tests/ZoneTest.php @@ -1,12 +1,10 @@ bucketName = $bucketName; @@ -104,12 +99,6 @@ class ZoneTest extends TestCase $this->assertContains('upload-z2.qiniup.com', $zone->cdnUpHosts); } - public function testZoneCnEast2() - { - $zone = Zone::zoneCnEast2(); - $this->assertContains('upload-cn-east-2.qiniup.com', $zone->cdnUpHosts); - } - public function testZoneNa0() { $zone = Zone::zoneNa0(); diff --git a/src/vendor/services.php b/src/vendor/services.php index dc1fd8c10..a047d0fe4 100644 --- a/src/vendor/services.php +++ b/src/vendor/services.php @@ -1,5 +1,5 @@ 'thans\\filesystem\\Service', diff --git a/src/vendor/setasign/fpdi/LICENSE.txt b/src/vendor/setasign/fpdi/LICENSE.txt new file mode 100644 index 000000000..84e590c11 --- /dev/null +++ b/src/vendor/setasign/fpdi/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Setasign GmbH & Co. KG, https://www.setasign.com + +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. \ No newline at end of file diff --git a/src/vendor/setasign/fpdi/README.md b/src/vendor/setasign/fpdi/README.md new file mode 100644 index 000000000..18998fb57 --- /dev/null +++ b/src/vendor/setasign/fpdi/README.md @@ -0,0 +1,130 @@ +FPDI - Free PDF Document Importer +================================= + +[![Latest Stable Version](https://poser.pugx.org/setasign/fpdi/v/stable.svg)](https://packagist.org/packages/setasign/fpdi) +[![Total Downloads](https://poser.pugx.org/setasign/fpdi/downloads.svg)](https://packagist.org/packages/setasign/fpdi) +[![License](https://poser.pugx.org/setasign/fpdi/license.svg)](https://packagist.org/packages/setasign/fpdi) + +:heavy_exclamation_mark: This document refers to FPDI 2. Version 1 is deprecated and development is discontinued. :heavy_exclamation_mark: + +FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF +documents and use them as templates in [FPDF](http://www.fpdf.org), which was developed by Olivier Plathey. Apart +from a copy of [FPDF](http://www.fpdf.org), FPDI does not require any special PHP extensions. + +FPDI can also be used as an extension for [TCPDF](https://github.com/tecnickcom/TCPDF) or +[tFPDF](http://fpdf.org/en/script/script92.php), too. + +## Installation with [Composer](https://packagist.org/packages/setasign/fpdi) + +Because FPDI can be used with FPDF, TCPDF or tFPDF we haven't added a fixed dependency in the main +composer.json file. You need to add the dependency to the PDF generation library of your choice +yourself. + +To use FPDI with FPDF include following in your composer.json file: + +```json +{ + "require": { + "setasign/fpdf": "1.8.*", + "setasign/fpdi": "^2.5" + } +} +``` + +If you want to use TCPDF, you have to update your composer.json to: + +```json +{ + "require": { + "tecnickcom/tcpdf": "6.6.*", + "setasign/fpdi": "^2.5" + } +} +``` + +If you want to use tFPDF, you have to update your composer.json to: + +```json +{ + "require": { + "setasign/tfpdf": "1.33.*", + "setasign/fpdi": "^2.3" + } +} +``` + +## Manual Installation + +If you do not use composer, just require the autoload.php in the /src folder: + +```php +require_once('src/autoload.php'); +``` + +If you have a PSR-4 autoloader implemented, just register the src path as follows: +```php +$loader = new \Example\Psr4AutoloaderClass; +$loader->register(); +$loader->addNamespace('setasign\Fpdi', 'path/to/src/'); +``` + +## Changes to Version 1 + +Version 2 is a complete rewrite from scratch of FPDI which comes with: +- Namespaced code +- Clean and up-to-date code base and style +- PSR-4 compatible autoloading +- Performance improvements by up to 100% +- Less memory consumption +- Native support for reading PDFs from strings or stream-resources +- Support for documents with "invalid" data before their file-header +- Optimized page tree resolving +- Usage of individual exceptions +- Several test types (unit, functional and visual tests) + +We tried to keep the main methods and logical workflow the same as in version 1 but please +notice that there were incompatible changes which you should consider when updating to +version 2: +- You need to load the code using the `src/autoload.php` file instead of `classes/FPDI.php`. +- The classes and traits are namespaced now: `setasign\Fpdi` +- Page boundaries beginning with a slash, such as `/MediaBox`, are not supported anymore. Remove + the slash or use a constant of `PdfReader\PageBoundaries`. +- The parameters $x, $y, $width and $height of the `useTemplate()` or `getTemplateSize()` + method have more logical correct default values now. Passing `0` as width or height will + result in an `InvalidArgumentException` now. +- The return value of `getTemplateSize()` had changed to an array with more speaking keys + and reusability: Use `width` instead of `w` and `height` instead of `h`. +- If you want to use **FPDI with TCPDF** you need to refactor your code to use the class `Tcpdf\Fpdi` +(since 2.1; before it was `TcpdfFpdi`) instead of `FPDI`. + +## Example and Documentation + +A simple example, that imports a single page and places this onto a new created page: + +```php +AddPage(); +// set the source file +$pdf->setSourceFile("Fantastic-Speaker.pdf"); +// import page 1 +$tplId = $pdf->importPage(1); +// use the imported page and place it at point 10,10 with a width of 100 mm +$pdf->useTemplate($tplId, 10, 10, 100); + +$pdf->Output(); +``` + +A full end-user documentation and API reference is available [here](https://manuals.setasign.com/fpdi-manual/). diff --git a/src/vendor/setasign/fpdi/SECURITY.md b/src/vendor/setasign/fpdi/SECURITY.md new file mode 100644 index 000000000..da9c516dd --- /dev/null +++ b/src/vendor/setasign/fpdi/SECURITY.md @@ -0,0 +1,5 @@ +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. diff --git a/src/vendor/setasign/fpdi/composer.json b/src/vendor/setasign/fpdi/composer.json new file mode 100644 index 000000000..c0eb4dfae --- /dev/null +++ b/src/vendor/setasign/fpdi/composer.json @@ -0,0 +1,51 @@ +{ + "name": "setasign/fpdi", + "homepage": "https://www.setasign.com/fpdi", + "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", + "type": "library", + "keywords": [ + "pdf", + "fpdi", + "fpdf" + ], + "license": "MIT", + "autoload": { + "psr-4": { + "setasign\\Fpdi\\": "src/" + } + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0", + "ext-zlib": "*" + }, + "conflict": { + "setasign/tfpdf": "<1.31" + }, + "authors": [ + { + "name": "Jan Slabon", + "email": "jan.slabon@setasign.com", + "homepage": "https://www.setasign.com" + }, + { + "name": "Maximilian Kresse", + "email": "maximilian.kresse@setasign.com", + "homepage": "https://www.setasign.com" + } + ], + "suggest": { + "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured." + }, + "require-dev": { + "phpunit/phpunit": "~5.7", + "setasign/fpdf": "~1.8.6", + "tecnickcom/tcpdf": "~6.2", + "setasign/tfpdf": "~1.33", + "squizlabs/php_codesniffer": "^3.5" + }, + "autoload-dev": { + "psr-4": { + "setasign\\Fpdi\\": "tests/" + } + } +} diff --git a/src/vendor/setasign/fpdi/src/FpdfTpl.php b/src/vendor/setasign/fpdi/src/FpdfTpl.php new file mode 100644 index 000000000..e6a15e7dc --- /dev/null +++ b/src/vendor/setasign/fpdi/src/FpdfTpl.php @@ -0,0 +1,21 @@ +currentTemplateId !== null) { + throw new \BadMethodCallException('The page format cannot be changed when writing to a template.'); + } + + if (!\in_array($orientation, ['P', 'L'], true)) { + throw new \InvalidArgumentException(\sprintf( + 'Invalid page orientation "%s"! Only "P" and "L" are allowed!', + $orientation + )); + } + + $size = $this->_getpagesize($size); + + if ( + $orientation != $this->CurOrientation + || $size[0] != $this->CurPageSize[0] + || $size[1] != $this->CurPageSize[1] + ) { + // New size or orientation + if ($orientation === 'P') { + $this->w = $size[0]; + $this->h = $size[1]; + } else { + $this->w = $size[1]; + $this->h = $size[0]; + } + $this->wPt = $this->w * $this->k; + $this->hPt = $this->h * $this->k; + $this->PageBreakTrigger = $this->h - $this->bMargin; + $this->CurOrientation = $orientation; + $this->CurPageSize = $size; + + $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt); + } + } + + /** + * Draws a template onto the page or another template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param array|float|int $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see FpdfTplTrait::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (!isset($this->templates[$tpl])) { + throw new \InvalidArgumentException('Template does not exist!'); + } + + if (\is_array($x)) { + unset($x['tpl']); + \extract($x, EXTR_IF_EXISTS); + /** @noinspection NotOptimalIfConditionsInspection */ + /** @phpstan-ignore function.alreadyNarrowedType */ + if (\is_array($x)) { + $x = 0; + } + } + + $template = $this->templates[$tpl]; + + $originalSize = $this->getTemplateSize($tpl); + $newSize = $this->getTemplateSize($tpl, $width, $height); + if ($adjustPageSize) { + $this->setPageFormat($newSize, $newSize['orientation']); + } + + $this->_out( + // reset standard values, translate and scale + \sprintf( + 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q', + ($newSize['width'] / $originalSize['width']), + ($newSize['height'] / $originalSize['height']), + $x * $this->k, + ($this->h - $y - $newSize['height']) * $this->k, + $template['id'] + ) + ); + + return $newSize; + } + + /** + * Get the size of a template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + if (!isset($this->templates[$tpl])) { + return false; + } + + if ($width === null && $height === null) { + $width = $this->templates[$tpl]['width']; + $height = $this->templates[$tpl]['height']; + } elseif ($width === null) { + $width = $height * $this->templates[$tpl]['width'] / $this->templates[$tpl]['height']; + } + + if ($height === null) { + $height = $width * $this->templates[$tpl]['height'] / $this->templates[$tpl]['width']; + } + + if ($height <= 0. || $width <= 0.) { + throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.'); + } + + return [ + 'width' => $width, + 'height' => $height, + 0 => $width, + 1 => $height, + 'orientation' => $width > $height ? 'L' : 'P' + ]; + } + + /** + * Begins a new template. + * + * @param float|int|null $width The width of the template. If null, the current page width is used. + * @param float|int|null $height The height of the template. If null, the current page height is used. + * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used). + * @return int A template identifier. + */ + public function beginTemplate($width = null, $height = null, $groupXObject = false) + { + if ($width === null) { + $width = $this->w; + } + + if ($height === null) { + $height = $this->h; + } + + $templateId = $this->getNextTemplateId(); + + // initiate buffer with current state of FPDF + $buffer = "2 J\n" + . \sprintf('%.2F w', $this->LineWidth * $this->k) . "\n"; + + if ($this->FontFamily) { + $buffer .= \sprintf("BT /F%d %.2F Tf ET\n", $this->CurrentFont['i'], $this->FontSizePt); + } + + if ($this->DrawColor !== '0 G') { + $buffer .= $this->DrawColor . "\n"; + } + if ($this->FillColor !== '0 g') { + $buffer .= $this->FillColor . "\n"; + } + + if ($groupXObject && \version_compare('1.4', $this->PDFVersion, '>')) { + $this->PDFVersion = '1.4'; + } + + $this->templates[$templateId] = [ + 'objectNumber' => null, + 'id' => 'TPL' . $templateId, + 'buffer' => $buffer, + 'width' => $width, + 'height' => $height, + 'groupXObject' => $groupXObject, + 'state' => [ + 'x' => $this->x, + 'y' => $this->y, + 'AutoPageBreak' => $this->AutoPageBreak, + 'bMargin' => $this->bMargin, + 'tMargin' => $this->tMargin, + 'lMargin' => $this->lMargin, + 'rMargin' => $this->rMargin, + 'h' => $this->h, + 'hPt' => $this->hPt, + 'w' => $this->w, + 'wPt' => $this->wPt, + 'FontFamily' => $this->FontFamily, + 'FontStyle' => $this->FontStyle, + 'FontSizePt' => $this->FontSizePt, + 'FontSize' => $this->FontSize, + 'underline' => $this->underline, + 'TextColor' => $this->TextColor, + 'DrawColor' => $this->DrawColor, + 'FillColor' => $this->FillColor, + 'ColorFlag' => $this->ColorFlag + ] + ]; + + $this->SetAutoPageBreak(false); + $this->currentTemplateId = $templateId; + + $this->h = $height; + $this->hPt = $height * $this->k; + $this->w = $width; + $this->wPt = $width * $this->k; + + $this->SetXY($this->lMargin, $this->tMargin); + $this->SetRightMargin($this->w - $width + $this->rMargin); + + return $templateId; + } + + /** + * Ends a template. + * + * @return bool|int|null A template identifier. + */ + public function endTemplate() + { + if ($this->currentTemplateId === null) { + return false; + } + + $templateId = $this->currentTemplateId; + $template = $this->templates[$templateId]; + + $state = $template['state']; + $this->SetXY($state['x'], $state['y']); + $this->tMargin = $state['tMargin']; + $this->lMargin = $state['lMargin']; + $this->rMargin = $state['rMargin']; + $this->h = $state['h']; + $this->hPt = $state['hPt']; + $this->w = $state['w']; + $this->wPt = $state['wPt']; + $this->SetAutoPageBreak($state['AutoPageBreak'], $state['bMargin']); + + $this->FontFamily = $state['FontFamily']; + $this->FontStyle = $state['FontStyle']; + $this->FontSizePt = $state['FontSizePt']; + $this->FontSize = $state['FontSize']; + + $this->TextColor = $state['TextColor']; + $this->DrawColor = $state['DrawColor']; + $this->FillColor = $state['FillColor']; + $this->ColorFlag = $state['ColorFlag']; + + $this->underline = $state['underline']; + + $fontKey = $this->FontFamily . $this->FontStyle; + if ($fontKey) { + $this->CurrentFont =& $this->fonts[$fontKey]; + } else { + unset($this->CurrentFont); + } + + $this->currentTemplateId = null; + + return $templateId; + } + + /** + * Get the next template id. + * + * @return int + */ + protected function getNextTemplateId() + { + return $this->templateId++; + } + + /* overwritten FPDF methods: */ + + /** + * @inheritdoc + */ + public function AddPage($orientation = '', $size = '', $rotation = 0) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Pages cannot be added when writing to a template.'); + } + parent::AddPage($orientation, $size, $rotation); + } + + /** + * @inheritdoc + */ + public function Link($x, $y, $w, $h, $link) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + parent::Link($x, $y, $w, $h, $link); + } + + /** + * @inheritdoc + */ + public function SetLink($link, $y = 0, $page = -1) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + return parent::SetLink($link, $y, $page); + } + + /** + * @inheritdoc + */ + public function SetDrawColor($r, $g = null, $b = null) + { + parent::SetDrawColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->DrawColor); + } + } + + /** + * @inheritdoc + */ + public function SetFillColor($r, $g = null, $b = null) + { + parent::SetFillColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->FillColor); + } + } + + /** + * @inheritdoc + */ + public function SetLineWidth($width) + { + parent::SetLineWidth($width); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('%.2F w', $width * $this->k)); + } + } + + /** + * @inheritdoc + */ + public function SetFont($family, $style = '', $size = 0) + { + parent::SetFont($family, $style, $size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + /** + * @inheritdoc + */ + public function SetFontSize($size) + { + parent::SetFontSize($size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + protected function _putimages() + { + parent::_putimages(); + + foreach ($this->templates as $key => $template) { + $this->_newobj(); + $this->templates[$key]['objectNumber'] = $this->n; + + $this->_put('<_put(\sprintf( + '/BBox[0 0 %.2F %.2F]', + $template['width'] * $this->k, + $template['height'] * $this->k + )); + $this->_put('/Resources 2 0 R'); // default resources dictionary of FPDF + + if ($this->compress) { + $buffer = \gzcompress($template['buffer']); + $this->_put('/Filter/FlateDecode'); + } else { + $buffer = $template['buffer']; + } + + $this->_put('/Length ' . \strlen($buffer)); + + if ($template['groupXObject']) { + $this->_put('/Group <>'); + } + + $this->_put('>>'); + $this->_putstream($buffer); + $this->_put('endobj'); + } + } + + /** + * @inheritdoc + */ + protected function _putxobjectdict() + { + foreach ($this->templates as $key => $template) { + $this->_put('/' . $template['id'] . ' ' . $template['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @inheritdoc + */ + public function _out($s) + { + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['buffer'] .= $s . "\n"; + } else { + parent::_out($s); + } + } +} diff --git a/src/vendor/setasign/fpdi/src/FpdfTrait.php b/src/vendor/setasign/fpdi/src/FpdfTrait.php new file mode 100644 index 000000000..e48ee9d9c --- /dev/null +++ b/src/vendor/setasign/fpdi/src/FpdfTrait.php @@ -0,0 +1,193 @@ +cleanUp(); + } + + /** + * Draws an imported page or a template onto the page or another template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see Fpdi::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (isset($this->importedPages[$tpl])) { + $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl; + } + return $size; + } + + return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize); + } + + /** + * Get the size of an imported page or template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + $size = parent::getTemplateSize($tpl, $width, $height); + if ($size === false) { + return $this->getImportedPageSize($tpl, $width, $height); + } + + return $size; + } + + /** + * @throws CrossReferenceException + * @throws PdfParserException + */ + protected function _putimages() + { + $this->currentReaderId = null; + parent::_putimages(); + + foreach ($this->importedPages as $key => $pageData) { + $this->_newobj(); + $this->importedPages[$key]['objectNumber'] = $this->n; + $this->currentReaderId = $pageData['readerId']; + $this->writePdfType($pageData['stream']); + $this->_put('endobj'); + } + + foreach (\array_keys($this->readers) as $readerId) { + $parser = $this->getPdfReader($readerId)->getParser(); + $this->currentReaderId = $readerId; + + while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { + try { + $object = $parser->getIndirectObject($objectNumber); + } catch (CrossReferenceException $e) { + if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { + $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); + } else { + throw $e; + } + } + + $this->writePdfType($object); + } + } + + $this->currentReaderId = null; + } + + /** + * @inheritdoc + */ + protected function _putxobjectdict() + { + foreach ($this->importedPages as $pageData) { + $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @param int $n + * @return void + * @throws PdfParser\Type\PdfTypeException + */ + protected function _putlinks($n) + { + foreach ($this->PageLinks[$n] as $pl) { + $this->_newobj(); + $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]); + $this->_put('<_put('/A <_escape($pl[4]) . ')>>'); + $values = $pl['importedLink']['pdfObject']->value; + + foreach ($values as $name => $entry) { + $this->_put('/' . $name . ' ', false); + $this->writePdfType($entry); + } + + if (isset($pl['quadPoints'])) { + $s = '/QuadPoints['; + foreach ($pl['quadPoints'] as $value) { + $s .= sprintf('%.2F ', $value); + } + $s .= ']'; + $this->_put($s); + } + } else { + $this->_put('/A <_textstring($pl[4]) . '>>'); + $this->_put('/Border [0 0 0]', false); + } + $this->_put('>>'); + } else { + $this->_put('/Border [0 0 0] ', false); + $l = $this->links[$pl[4]]; + if (isset($this->PageInfo[$l[0]]['size'])) { + $h = $this->PageInfo[$l[0]]['size'][1]; + } else { + $h = ($this->DefOrientation === 'P') + ? $this->DefPageSize[1] * $this->k + : $this->DefPageSize[0] * $this->k; + } + $this->_put(sprintf( + '/Dest [%d 0 R /XYZ 0 %.2F null]>>', + $this->PageInfo[$l[0]]['n'], + $h - $l[1] * $this->k + )); + } + $this->_put('endobj'); + } + } + + protected function _put($s, $newLine = true) + { + if ($newLine) { + $this->buffer .= $s . "\n"; + } else { + $this->buffer .= $s; + } + } +} diff --git a/src/vendor/setasign/fpdi/src/Fpdi.php b/src/vendor/setasign/fpdi/src/Fpdi.php new file mode 100644 index 000000000..7d4a1a586 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/Fpdi.php @@ -0,0 +1,34 @@ +readers) : $this->createdReaders; + foreach ($readers as $id) { + $this->readers[$id]->getParser()->getStreamReader()->cleanUp(); + unset($this->readers[$id]); + } + + $this->createdReaders = []; + } + + /** + * Set the minimal PDF version. + * + * @param string $pdfVersion + */ + protected function setMinPdfVersion($pdfVersion) + { + if (\version_compare($pdfVersion, $this->PDFVersion, '>')) { + $this->PDFVersion = $pdfVersion; + } + } + + /** @noinspection PhpUndefinedClassInspection */ + /** + * Get a new pdf parser instance. + * + * @param StreamReader $streamReader + * @param array $parserParams Individual parameters passed to the parser instance. + * @return PdfParser|FpdiPdfParser + */ + protected function getPdfParserInstance(StreamReader $streamReader, array $parserParams = []) + { + // note: if you get an exception here - turn off errors/warnings on not found classes for your autoloader. + // psr-4 (https://www.php-fig.org/psr/psr-4/) says: Autoloader implementations MUST NOT throw + // exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value. + /** @noinspection PhpUndefinedClassInspection */ + if (\class_exists(FpdiPdfParser::class)) { + /** @noinspection PhpUndefinedClassInspection */ + return new FpdiPdfParser($streamReader, $parserParams); + } + + return new PdfParser($streamReader); + } + + /** + * Get an unique reader id by the $file parameter. + * + * @param string|resource|PdfReader|StreamReader $file An open file descriptor, a path to a file, a PdfReader + * instance or a StreamReader instance. + * @param array $parserParams Individual parameters passed to the parser instance. + * @return string + */ + protected function getPdfReaderId($file, array $parserParams = []) + { + if (\is_resource($file)) { + $id = (string) $file; + } elseif (\is_string($file)) { + $id = \realpath($file); + if ($id === false) { + $id = $file; + } + } elseif (\is_object($file)) { + $id = \spl_object_hash($file); + } else { + throw new \InvalidArgumentException( + \sprintf('Invalid type in $file parameter (%s)', \gettype($file)) + ); + } + + /** @noinspection OffsetOperationsInspection */ + if (isset($this->readers[$id])) { + return $id; + } + + if (\is_resource($file)) { + $streamReader = new StreamReader($file); + } elseif (\is_string($file)) { + $streamReader = StreamReader::createByFile($file); + $this->createdReaders[] = $id; + } else { + $streamReader = $file; + } + + $reader = new PdfReader($this->getPdfParserInstance($streamReader, $parserParams)); + /** @noinspection OffsetOperationsInspection */ + $this->readers[$id] = $reader; + + return $id; + } + + /** + * Get a pdf reader instance by its id. + * + * @param string $id + * @return PdfReader + */ + protected function getPdfReader($id) + { + if (isset($this->readers[$id])) { + return $this->readers[$id]; + } + + throw new \InvalidArgumentException( + \sprintf('No pdf reader with the given id (%s) exists.', $id) + ); + } + + /** + * Set the source PDF file. + * + * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance. + * @return int The page count of the PDF document. + * @throws PdfParserException + */ + public function setSourceFile($file) + { + return $this->setSourceFileWithParserParams($file); + } + + /** + * Set the source PDF file with parameters which are passed to the parser instance. + * + * This method allows us to pass e.g. authentication information to the parser instance. + * + * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance. + * @param array $parserParams Individual parameters passed to the parser instance. + * @return int The page count of the PDF document. + * @throws CrossReferenceException + * @throws PdfParserException + * @throws PdfTypeException + */ + public function setSourceFileWithParserParams($file, array $parserParams = []) + { + $this->currentReaderId = $this->getPdfReaderId($file, $parserParams); + $this->objectsToCopy[$this->currentReaderId] = []; + + $reader = $this->getPdfReader($this->currentReaderId); + $this->setMinPdfVersion($reader->getPdfVersion()); + + return $reader->getPageCount(); + } + + /** + * Imports a page. + * + * @param int $pageNumber The page number. + * @param string $box The page boundary to import. Default set to PageBoundaries::CROP_BOX. + * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used). + * @param bool $importExternalLinks Define whether external links are imported or not. + * @return string A unique string identifying the imported page. + * @throws CrossReferenceException + * @throws FilterException + * @throws PdfParserException + * @throws PdfTypeException + * @throws PdfReaderException + * @see PageBoundaries + */ + public function importPage( + $pageNumber, + $box = PageBoundaries::CROP_BOX, + $groupXObject = true, + $importExternalLinks = false + ) { + if ($this->currentReaderId === null) { + throw new \BadMethodCallException('No reader initiated. Call setSourceFile() first.'); + } + + $pageId = $this->currentReaderId; + + $pageNumber = (int)$pageNumber; + $pageId .= '|' . $pageNumber . '|' . ($groupXObject ? '1' : '0') . '|' . ($importExternalLinks ? '1' : '0'); + + // for backwards compatibility with FPDI 1 + $box = \ltrim($box, '/'); + if (!PageBoundaries::isValidName($box)) { + throw new \InvalidArgumentException( + \sprintf('Box name is invalid: "%s"', $box) + ); + } + + $pageId .= '|' . $box; + + if (isset($this->importedPages[$pageId])) { + return $pageId; + } + + $reader = $this->getPdfReader($this->currentReaderId); + $page = $reader->getPage($pageNumber); + + $bbox = $page->getBoundary($box); + if ($bbox === false) { + throw new PdfReaderException( + \sprintf("Page doesn't have a boundary box (%s).", $box), + PdfReaderException::MISSING_DATA + ); + } + + $dict = new PdfDictionary(); + $dict->value['Type'] = PdfName::create('XObject'); + $dict->value['Subtype'] = PdfName::create('Form'); + $dict->value['FormType'] = PdfNumeric::create(1); + $dict->value['BBox'] = $bbox->toPdfArray(); + + if ($groupXObject) { + $this->setMinPdfVersion('1.4'); + $dict->value['Group'] = PdfDictionary::create([ + 'Type' => PdfName::create('Group'), + 'S' => PdfName::create('Transparency') + ]); + } + + $resources = $page->getAttribute('Resources'); + if ($resources !== null) { + $dict->value['Resources'] = $resources; + } + + list($width, $height) = $page->getWidthAndHeight($box); + + $a = 1; + $b = 0; + $c = 0; + $d = 1; + $e = -$bbox->getLlx(); + $f = -$bbox->getLly(); + + $rotation = $page->getRotation(); + + if ($rotation !== 0) { + $rotation *= -1; + $angle = $rotation * M_PI / 180; + $a = \cos($angle); + $b = \sin($angle); + $c = -$b; + $d = $a; + + switch ($rotation) { + case -90: + $e = -$bbox->getLly(); + $f = $bbox->getUrx(); + break; + case -180: + $e = $bbox->getUrx(); + $f = $bbox->getUry(); + break; + case -270: + $e = $bbox->getUry(); + $f = -$bbox->getLlx(); + break; + } + } + + // we need to rotate/translate + if ($a != 1 || $b != 0 || $c != 0 || $d != 1 || $e != 0 || $f != 0) { + $dict->value['Matrix'] = PdfArray::create([ + PdfNumeric::create($a), PdfNumeric::create($b), PdfNumeric::create($c), + PdfNumeric::create($d), PdfNumeric::create($e), PdfNumeric::create($f) + ]); + } + + // try to use the existing content stream + $pageDict = $page->getPageDictionary(); + + try { + $contentsObject = PdfType::resolve(PdfDictionary::get($pageDict, 'Contents'), $reader->getParser(), true); + $contents = PdfType::resolve($contentsObject, $reader->getParser()); + + // just copy the stream reference if it is only a single stream + if ( + ($contentsIsStream = ($contents instanceof PdfStream)) + || ($contents instanceof PdfArray && \count($contents->value) === 1) + ) { + if ($contentsIsStream) { + /** + * @var PdfIndirectObject $contentsObject + */ + $stream = $contents; + } else { + $stream = PdfType::resolve($contents->value[0], $reader->getParser()); + } + + $filter = PdfDictionary::get($stream->value, 'Filter'); + if (!$filter instanceof PdfNull) { + $dict->value['Filter'] = $filter; + } + $length = PdfType::resolve(PdfDictionary::get($stream->value, 'Length'), $reader->getParser()); + $dict->value['Length'] = $length; + $stream->value = $dict; + // otherwise extract it from the array and re-compress the whole stream + } else { + $streamContent = $this->compress + ? \gzcompress($page->getContentStream()) + : $page->getContentStream(); + + $dict->value['Length'] = PdfNumeric::create(\strlen($streamContent)); + if ($this->compress) { + $dict->value['Filter'] = PdfName::create('FlateDecode'); + } + + $stream = PdfStream::create($dict, $streamContent); + } + // Catch faulty pages and use an empty content stream + } catch (FpdiException $e) { + $dict->value['Length'] = PdfNumeric::create(0); + $stream = PdfStream::create($dict, ''); + } + + $externalLinks = []; + if ($importExternalLinks) { + $externalLinks = $page->getExternalLinks($box); + } + + $this->importedPages[$pageId] = [ + 'objectNumber' => null, + 'readerId' => $this->currentReaderId, + 'id' => 'TPL' . $this->getNextTemplateId(), + 'width' => $width / $this->k, + 'height' => $height / $this->k, + 'stream' => $stream, + 'externalLinks' => $externalLinks + ]; + + return $pageId; + } + + /** + * Draws an imported page onto the page. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $pageId The page id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size. + * @see Fpdi::getTemplateSize() + */ + public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (\is_array($x)) { + /** @noinspection OffsetOperationsInspection */ + unset($x['pageId']); + \extract($x, EXTR_IF_EXISTS); + /** @noinspection NotOptimalIfConditionsInspection */ + /** @phpstan-ignore function.alreadyNarrowedType */ + if (\is_array($x)) { + $x = 0; + } + } + + if (!isset($this->importedPages[$pageId])) { + throw new \InvalidArgumentException('Imported page does not exist!'); + } + + $importedPage = $this->importedPages[$pageId]; + + $originalSize = $this->getTemplateSize($pageId); + $newSize = $this->getTemplateSize($pageId, $width, $height); + if ($adjustPageSize) { + $this->setPageFormat($newSize, $newSize['orientation']); + } + + $scaleX = ($newSize['width'] / $originalSize['width']); + $scaleY = ($newSize['height'] / $originalSize['height']); + $xPt = $x * $this->k; + $yPt = $y * $this->k; + $newHeightPt = $newSize['height'] * $this->k; + + $this->_out( + // reset standard values, translate and scale + \sprintf( + 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q', + $scaleX, + $scaleY, + $xPt, + $this->hPt - $yPt - $newHeightPt, + $importedPage['id'] + ) + ); + + if (count($importedPage['externalLinks']) > 0) { + foreach ($importedPage['externalLinks'] as $externalLink) { + // mPDF uses also 'externalLinks' but doesn't come with a rect-value + if (!isset($externalLink['rect'])) { + continue; + } + + /** @var Rectangle $rect */ + $rect = $externalLink['rect']; + $this->Link( + $x + $rect->getLlx() / $this->k * $scaleX, + $y + $newSize['height'] - ($rect->getLly() + $rect->getHeight()) / $this->k * $scaleY, + $rect->getWidth() / $this->k * $scaleX, + $rect->getHeight() / $this->k * $scaleY, + $externalLink['uri'] + ); + + $this->adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage); + } + } + + return $newSize; + } + + /** + * This method will add additional data to the last created link/annotation. + * + * It is separated because TCPDF uses its own logic to handle link annotations. + * This method is overwritten in the TCPDF implementation. + * + * @param array $externalLink + * @param float|int $xPt + * @param float|int $scaleX + * @param float|int $yPt + * @param float|int $newHeightPt + * @param float|int $scaleY + * @param array $importedPage + * @return void + */ + protected function adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage) + { + // let's create a relation of the newly created link to the data of the external link + $lastLink = count($this->PageLinks[$this->page]); + $this->PageLinks[$this->page][$lastLink - 1]['importedLink'] = $externalLink; + if (count($externalLink['quadPoints']) > 0) { + $quadPoints = []; + for ($i = 0, $n = count($externalLink['quadPoints']); $i < $n; $i += 2) { + $quadPoints[] = $xPt + $externalLink['quadPoints'][$i] * $scaleX; + $quadPoints[] = $this->hPt - $yPt - $newHeightPt + $externalLink['quadPoints'][$i + 1] * $scaleY; + } + + $this->PageLinks[$this->page][$lastLink - 1]['quadPoints'] = $quadPoints; + } + } + + /** + * Get the size of an imported page. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getImportedPageSize($tpl, $width = null, $height = null) + { + if (isset($this->importedPages[$tpl])) { + $importedPage = $this->importedPages[$tpl]; + + if ($width === null && $height === null) { + $width = $importedPage['width']; + $height = $importedPage['height']; + } elseif ($width === null) { + $width = $height * $importedPage['width'] / $importedPage['height']; + } + + if ($height === null) { + $height = $width * $importedPage['height'] / $importedPage['width']; + } + + if ($height <= 0. || $width <= 0.) { + throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.'); + } + + return [ + 'width' => $width, + 'height' => $height, + 0 => $width, + 1 => $height, + 'orientation' => $width > $height ? 'L' : 'P' + ]; + } + + return false; + } + + /** + * Writes a PdfType object to the resulting buffer. + * + * @param PdfType $value + * @throws PdfTypeException + */ + protected function writePdfType(PdfType $value) + { + if ($value instanceof PdfNumeric) { + if (\is_int($value->value)) { + $this->_put($value->value . ' ', false); + } else { + $this->_put(\rtrim(\rtrim(\sprintf('%.5F', $value->value), '0'), '.') . ' ', false); + } + } elseif ($value instanceof PdfName) { + $this->_put('/' . $value->value . ' ', false); + } elseif ($value instanceof PdfString) { + $this->_put('(' . $value->value . ')', false); + } elseif ($value instanceof PdfHexString) { + $this->_put('<' . $value->value . '>', false); + } elseif ($value instanceof PdfBoolean) { + $this->_put($value->value ? 'true ' : 'false ', false); + } elseif ($value instanceof PdfArray) { + $this->_put('[', false); + foreach ($value->value as $entry) { + $this->writePdfType($entry); + } + $this->_put(']'); + } elseif ($value instanceof PdfDictionary) { + $this->_put('<<', false); + foreach ($value->value as $name => $entry) { + $this->_put('/' . $name . ' ', false); + $this->writePdfType($entry); + } + $this->_put('>>'); + } elseif ($value instanceof PdfToken) { + $this->_put($value->value); + } elseif ($value instanceof PdfNull) { + $this->_put('null ', false); + } elseif ($value instanceof PdfStream) { + $this->writePdfType($value->value); + $this->_put('stream'); + $this->_put($value->getStream()); + $this->_put('endstream'); + } elseif ($value instanceof PdfIndirectObjectReference) { + if (!isset($this->objectMap[$this->currentReaderId])) { + $this->objectMap[$this->currentReaderId] = []; + } + + if (!isset($this->objectMap[$this->currentReaderId][$value->value])) { + $this->objectMap[$this->currentReaderId][$value->value] = ++$this->n; + $this->objectsToCopy[$this->currentReaderId][] = $value->value; + } + + $this->_put($this->objectMap[$this->currentReaderId][$value->value] . ' 0 R ', false); + } elseif ($value instanceof PdfIndirectObject) { + $n = $this->objectMap[$this->currentReaderId][$value->objectNumber]; + $this->_newobj($n); + $this->writePdfType($value->value); + + // add newline before "endobj" for all objects in view to PDF/A conformance + if ( + !( + ($value->value instanceof PdfArray) || + ($value->value instanceof PdfDictionary) || + ($value->value instanceof PdfToken) || + ($value->value instanceof PdfStream) + ) + ) { + $this->_put("\n", false); + } + + $this->_put('endobj'); + } + } +} diff --git a/src/vendor/setasign/fpdi/src/GraphicsState.php b/src/vendor/setasign/fpdi/src/GraphicsState.php new file mode 100644 index 000000000..6923c38a2 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/GraphicsState.php @@ -0,0 +1,99 @@ +ctm = $ctm; + } + + /** + * @param Matrix $matrix + * @return $this + */ + public function add(Matrix $matrix) + { + $this->ctm = $matrix->multiply($this->ctm); + return $this; + } + + /** + * @param int|float $x + * @param int|float $y + * @param int|float $angle + * @return $this + */ + public function rotate($x, $y, $angle) + { + if (abs($angle) < 1e-5) { + return $this; + } + + $angle = deg2rad($angle); + $c = cos($angle); + $s = sin($angle); + + $this->add(new Matrix($c, $s, -$s, $c, $x, $y)); + + return $this->translate(-$x, -$y); + } + + /** + * @param int|float $shiftX + * @param int|float $shiftY + * @return $this + */ + public function translate($shiftX, $shiftY) + { + return $this->add(new Matrix(1, 0, 0, 1, $shiftX, $shiftY)); + } + + /** + * @param int|float $scaleX + * @param int|float $scaleY + * @return $this + */ + public function scale($scaleX, $scaleY) + { + return $this->add(new Matrix($scaleX, 0, 0, $scaleY, 0, 0)); + } + + /** + * @param Vector $vector + * @return Vector + */ + public function toUserSpace(Vector $vector) + { + return $vector->multiplyWithMatrix($this->ctm); + } +} diff --git a/src/vendor/setasign/fpdi/src/Math/Matrix.php b/src/vendor/setasign/fpdi/src/Math/Matrix.php new file mode 100644 index 000000000..578bdc884 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/Math/Matrix.php @@ -0,0 +1,116 @@ +a = (float)$a; + $this->b = (float)$b; + $this->c = (float)$c; + $this->d = (float)$d; + $this->e = (float)$e; + $this->f = (float)$f; + } + + /** + * @return float[] + */ + public function getValues() + { + return [$this->a, $this->b, $this->c, $this->d, $this->e, $this->f]; + } + + /** + * @param Matrix $by + * @return Matrix + */ + public function multiply(self $by) + { + $a = + $this->a * $by->a + + $this->b * $by->c + //+ 0 * $by->e + ; + + $b = + $this->a * $by->b + + $this->b * $by->d + //+ 0 * $by->f + ; + + $c = + $this->c * $by->a + + $this->d * $by->c + //+ 0 * $by->e + ; + + $d = + $this->c * $by->b + + $this->d * $by->d + //+ 0 * $by->f + ; + + $e = + $this->e * $by->a + + $this->f * $by->c + + /*1 * */$by->e; + + $f = + $this->e * $by->b + + $this->f * $by->d + + /*1 * */$by->f; + + return new self($a, $b, $c, $d, $e, $f); + } +} diff --git a/src/vendor/setasign/fpdi/src/Math/Vector.php b/src/vendor/setasign/fpdi/src/Math/Vector.php new file mode 100644 index 000000000..fe2034829 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/Math/Vector.php @@ -0,0 +1,66 @@ +x = (float)$x; + $this->y = (float)$y; + } + + /** + * @return float + */ + public function getX() + { + return $this->x; + } + + /** + * @return float + */ + public function getY() + { + return $this->y; + } + + /** + * @param Matrix $matrix + * @return Vector + */ + public function multiplyWithMatrix(Matrix $matrix) + { + list($a, $b, $c, $d, $e, $f) = $matrix->getValues(); + $x = $a * $this->x + $c * $this->y + $e; + $y = $b * $this->x + $d * $this->y + $f; + + return new self($x, $y); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php new file mode 100644 index 000000000..8953e6370 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/AbstractReader.php @@ -0,0 +1,95 @@ +parser = $parser; + $this->readTrailer(); + } + + /** + * Get the trailer dictionary. + * + * @return PdfDictionary + */ + public function getTrailer() + { + return $this->trailer; + } + + /** + * Read the trailer dictionary. + * + * @throws CrossReferenceException + * @throws PdfTypeException + */ + protected function readTrailer() + { + try { + $trailerKeyword = $this->parser->readValue(null, PdfToken::class); + if ($trailerKeyword->value !== 'trailer') { + throw new CrossReferenceException( + \sprintf( + 'Unexpected end of cross reference. "trailer"-keyword expected, got: %s.', + $trailerKeyword->value + ), + CrossReferenceException::UNEXPECTED_END + ); + } + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + 'Unexpected end of cross reference. "trailer"-keyword expected, got an invalid object type.', + CrossReferenceException::UNEXPECTED_END, + $e + ); + } + + try { + $trailer = $this->parser->readValue(null, PdfDictionary::class); + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + 'Unexpected end of cross reference. Trailer not found.', + CrossReferenceException::UNEXPECTED_END, + $e + ); + } + + $this->trailer = $trailer; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php new file mode 100644 index 000000000..1cbe0e216 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReference.php @@ -0,0 +1,326 @@ +parser = $parser; + $this->fileHeaderOffset = $fileHeaderOffset; + + $offset = $this->findStartXref(); + $reader = null; + /** @noinspection TypeUnsafeComparisonInspection */ + while ($offset != false) { // By doing an unsafe comparsion we ignore faulty references to byte offset 0 + try { + $reader = $this->readXref($offset + $this->fileHeaderOffset); + } catch (CrossReferenceException $e) { + // sometimes the file header offset is part of the byte offsets, so let's retry by resetting it to zero. + if ($e->getCode() === CrossReferenceException::INVALID_DATA && $this->fileHeaderOffset !== 0) { + $this->fileHeaderOffset = 0; + $reader = $this->readXref($offset); + } else { + throw $e; + } + } + + $trailer = $reader->getTrailer(); + $this->checkForEncryption($trailer); + $this->readers[] = $reader; + + if (isset($trailer->value['Prev'])) { + $offset = $trailer->value['Prev']->value; + } else { + $offset = false; + } + } + + // fix faulty sub-section header + if ($reader instanceof FixedReader) { + /** + * @var FixedReader $reader + */ + $reader->fixFaultySubSectionShift(); + } + + if ($reader === null) { + throw new CrossReferenceException('No cross-reference found.', CrossReferenceException::NO_XREF_FOUND); + } + } + + /** + * Get the size of the cross reference. + * + * @return integer + */ + public function getSize() + { + return $this->getTrailer()->value['Size']->value; + } + + /** + * Get the trailer dictionary. + * + * @return PdfDictionary + */ + public function getTrailer() + { + return $this->readers[0]->getTrailer(); + } + + /** + * Get the cross reference readser instances. + * + * @return ReaderInterface[] + */ + public function getReaders() + { + return $this->readers; + } + + /** + * Get the offset by an object number. + * + * @param int $objectNumber + * @return integer|bool + */ + public function getOffsetFor($objectNumber) + { + foreach ($this->getReaders() as $reader) { + $offset = $reader->getOffsetFor($objectNumber); + if ($offset !== false) { + return $offset; + } + } + + return false; + } + + /** + * Get an indirect object by its object number. + * + * @param int $objectNumber + * @return PdfIndirectObject + * @throws CrossReferenceException + */ + public function getIndirectObject($objectNumber) + { + $offset = $this->getOffsetFor($objectNumber); + if ($offset === false) { + throw new CrossReferenceException( + \sprintf('Object (id:%s) not found.', $objectNumber), + CrossReferenceException::OBJECT_NOT_FOUND + ); + } + + $parser = $this->parser; + + $parser->getTokenizer()->clearStack(); + $parser->getStreamReader()->reset($offset + $this->fileHeaderOffset); + + try { + /** @var PdfIndirectObject $object */ + $object = $parser->readValue(null, PdfIndirectObject::class); + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + \sprintf('Object (id:%s) not found at location (%s).', $objectNumber, $offset), + CrossReferenceException::OBJECT_NOT_FOUND, + $e + ); + } + + if ($object->objectNumber !== $objectNumber) { + throw new CrossReferenceException( + \sprintf('Wrong object found, got %s while %s was expected.', $object->objectNumber, $objectNumber), + CrossReferenceException::OBJECT_NOT_FOUND + ); + } + + return $object; + } + + /** + * Read the cross-reference table at a given offset. + * + * Internally the method will try to evaluate the best reader for this cross-reference. + * + * @param int $offset + * @return ReaderInterface + * @throws CrossReferenceException + * @throws PdfTypeException + */ + protected function readXref($offset) + { + $this->parser->getStreamReader()->reset($offset); + $this->parser->getTokenizer()->clearStack(); + $initValue = $this->parser->readValue(); + + return $this->initReaderInstance($initValue); + } + + /** + * Get a cross-reference reader instance. + * + * @param PdfToken|PdfIndirectObject $initValue + * @return ReaderInterface|bool + * @throws CrossReferenceException + * @throws PdfTypeException + */ + protected function initReaderInstance($initValue) + { + $position = $this->parser->getStreamReader()->getPosition() + + $this->parser->getStreamReader()->getOffset() + $this->fileHeaderOffset; + + if ($initValue instanceof PdfToken && $initValue->value === 'xref') { + try { + return new FixedReader($this->parser); + } catch (CrossReferenceException $e) { + $this->parser->getStreamReader()->reset($position); + $this->parser->getTokenizer()->clearStack(); + + return new LineReader($this->parser); + } + } + + if ($initValue instanceof PdfIndirectObject) { + try { + $stream = PdfStream::ensure($initValue->value); + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + 'Invalid object type at xref reference offset.', + CrossReferenceException::INVALID_DATA, + $e + ); + } + + $type = PdfDictionary::get($stream->value, 'Type'); + if ($type->value !== 'XRef') { + throw new CrossReferenceException( + 'The xref position points to an incorrect object type.', + CrossReferenceException::INVALID_DATA + ); + } + + $this->checkForEncryption($stream->value); + + throw new CrossReferenceException( + 'This PDF document probably uses a compression technique which is not supported by the ' . + 'free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)', + CrossReferenceException::COMPRESSED_XREF + ); + } + + throw new CrossReferenceException( + 'The xref position points to an incorrect object type.', + CrossReferenceException::INVALID_DATA + ); + } + + /** + * Check for encryption. + * + * @param PdfDictionary $dictionary + * @throws CrossReferenceException + */ + protected function checkForEncryption(PdfDictionary $dictionary) + { + if (isset($dictionary->value['Encrypt'])) { + throw new CrossReferenceException( + 'This PDF document is encrypted and cannot be processed with FPDI.', + CrossReferenceException::ENCRYPTED + ); + } + } + + /** + * Find the start position for the first cross-reference. + * + * @return int The byte-offset position of the first cross-reference. + * @throws CrossReferenceException + */ + protected function findStartXref() + { + $reader = $this->parser->getStreamReader(); + $reader->reset(-self::$trailerSearchLength, self::$trailerSearchLength); + + $buffer = $reader->getBuffer(false); + $pos = \strrpos($buffer, 'startxref'); + $addOffset = 9; + if ($pos === false) { + // Some corrupted documents uses startref, instead of startxref + $pos = \strrpos($buffer, 'startref'); + if ($pos === false) { + throw new CrossReferenceException( + 'Unable to find pointer to xref table', + CrossReferenceException::NO_STARTXREF_FOUND + ); + } + $addOffset = 8; + } + + $reader->setOffset($pos + $addOffset); + + try { + $value = $this->parser->readValue(null, PdfNumeric::class); + } catch (PdfTypeException $e) { + throw new CrossReferenceException( + 'Invalid data after startxref keyword.', + CrossReferenceException::INVALID_DATA, + $e + ); + } + + return $value->value; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php new file mode 100644 index 000000000..412b375e4 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/CrossReferenceException.php @@ -0,0 +1,79 @@ +reader = $parser->getStreamReader(); + $this->read(); + parent::__construct($parser); + } + + /** + * Get all subsection data. + * + * @return array + */ + public function getSubSections() + { + return $this->subSections; + } + + /** + * @inheritdoc + * @return int|false + */ + public function getOffsetFor($objectNumber) + { + foreach ($this->subSections as $offset => list($startObject, $objectCount)) { + /** + * @var int $startObject + * @var int $objectCount + */ + if ($objectNumber >= $startObject && $objectNumber < ($startObject + $objectCount)) { + $position = $offset + 20 * ($objectNumber - $startObject); + $this->reader->ensure($position, 20); + $line = $this->reader->readBytes(20); + if ($line[17] === 'f') { + return false; + } + + return (int) \substr($line, 0, 10); + } + } + + return false; + } + + /** + * Read the cross-reference. + * + * This reader will only read the subsections in this method. The offsets were resolved individually by this + * information. + * + * @throws CrossReferenceException + */ + protected function read() + { + $subSections = []; + + $startObject = $entryCount = $lastLineStart = null; + $validityChecked = false; + while (($line = $this->reader->readLine(20)) !== false) { + if (\strpos($line, 'trailer') !== false) { + $this->reader->reset($lastLineStart); + break; + } + + // jump over if line content doesn't match the expected string + if (\sscanf($line, '%d %d', $startObject, $entryCount) !== 2) { + continue; + } + + $oldPosition = $this->reader->getPosition(); + $position = $oldPosition + $this->reader->getOffset(); + + if (!$validityChecked && $entryCount > 0) { + $nextLine = $this->reader->readBytes(21); + /* Check the next line for maximum of 20 bytes and not longer + * By catching 21 bytes and trimming the length should be still 21. + */ + if (\strlen(\trim($nextLine)) !== 21) { + throw new CrossReferenceException( + 'Cross-reference entries are larger than 20 bytes.', + CrossReferenceException::ENTRIES_TOO_LARGE + ); + } + + /* Check for less than 20 bytes: cut the line to 20 bytes and trim; have to result in exactly 18 bytes. + * If it would have less bytes the substring would get the first bytes of the next line which would + * evaluate to a 20 bytes long string after trimming. + */ + if (\strlen(\trim(\substr($nextLine, 0, 20))) !== 18) { + throw new CrossReferenceException( + 'Cross-reference entries are less than 20 bytes.', + CrossReferenceException::ENTRIES_TOO_SHORT + ); + } + + $validityChecked = true; + } + + $subSections[$position] = [$startObject, $entryCount]; + + $lastLineStart = $position + $entryCount * 20; + $this->reader->reset($lastLineStart); + } + + // reset after the last correct parsed line + $this->reader->reset($lastLineStart); + + if (\count($subSections) === 0) { + throw new CrossReferenceException( + 'No entries found in cross-reference.', + CrossReferenceException::NO_ENTRIES + ); + } + + $this->subSections = $subSections; + } + + /** + * Fixes an invalid object number shift. + * + * This method can be used to repair documents with an invalid subsection header: + * + * + * xref + * 1 7 + * 0000000000 65535 f + * 0000000009 00000 n + * 0000412075 00000 n + * 0000412172 00000 n + * 0000412359 00000 n + * 0000412417 00000 n + * 0000412468 00000 n + * + * + * It shall only be called on the first table. + * + * @return bool + */ + public function fixFaultySubSectionShift() + { + $subSections = $this->getSubSections(); + if (\count($subSections) > 1) { + return false; + } + + $subSection = \current($subSections); + if ($subSection[0] != 1) { + return false; + } + + if ($this->getOffsetFor(1) === false) { + foreach ($subSections as $offset => list($startObject, $objectCount)) { + $this->subSections[$offset] = [$startObject - 1, $objectCount]; + } + return true; + } + + return false; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php new file mode 100644 index 000000000..c921fe746 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/LineReader.php @@ -0,0 +1,168 @@ + 20 bytes). + */ +class LineReader extends AbstractReader implements ReaderInterface +{ + /** + * The object offsets. + * + * @var array + */ + protected $offsets; + + /** + * LineReader constructor. + * + * @param PdfParser $parser + * @throws CrossReferenceException + */ + public function __construct(PdfParser $parser) + { + $this->read($this->extract($parser->getStreamReader())); + parent::__construct($parser); + } + + /** + * @inheritdoc + * @return int|false + */ + public function getOffsetFor($objectNumber) + { + if (isset($this->offsets[$objectNumber])) { + return $this->offsets[$objectNumber][0]; + } + + return false; + } + + /** + * Get all found offsets. + * + * @return array + */ + public function getOffsets() + { + return $this->offsets; + } + + /** + * Extracts the cross reference data from the stream reader. + * + * @param StreamReader $reader + * @return string + * @throws CrossReferenceException + */ + protected function extract(StreamReader $reader) + { + $bytesPerCycle = 100; + $reader->reset(null, $bytesPerCycle); + + $cycles = 0; + do { + // 6 = length of "trailer" - 1 + $pos = \max(($bytesPerCycle * $cycles) - 6, 0); + $trailerPos = \strpos($reader->getBuffer(false), 'trailer', $pos); + $cycles++; + } while ($trailerPos === false && $reader->increaseLength($bytesPerCycle) !== false); + + if ($trailerPos === false) { + throw new CrossReferenceException( + 'Unexpected end of cross reference. "trailer"-keyword not found.', + CrossReferenceException::NO_TRAILER_FOUND + ); + } + + $xrefContent = \substr($reader->getBuffer(false), 0, $trailerPos); + $reader->reset($reader->getPosition() + $trailerPos); + + return $xrefContent; + } + + /** + * Read the cross-reference entries. + * + * @param string $xrefContent + * @throws CrossReferenceException + */ + protected function read($xrefContent) + { + // get eol markers in the first 100 bytes + \preg_match_all("/(\r\n|\n|\r)/", \substr($xrefContent, 0, 100), $m); + + if (\count($m[0]) === 0) { + throw new CrossReferenceException( + 'No data found in cross-reference.', + CrossReferenceException::INVALID_DATA + ); + } + + // count(array_count_values()) is faster then count(array_unique()) + // @see https://github.com/symfony/symfony/pull/23731 + // can be reverted for php7.2 + $differentLineEndings = \count(\array_count_values($m[0])); + if ($differentLineEndings > 1) { + $lines = \preg_split("/(\r\n|\n|\r)/", $xrefContent, -1, PREG_SPLIT_NO_EMPTY); + } else { + $lines = \explode($m[0][0], $xrefContent); + } + + unset($differentLineEndings, $m); + if (!\is_array($lines)) { + $this->offsets = []; + return; + } + + $start = 0; + $offsets = []; + + // trim all lines and remove empty lines + $lines = \array_filter(\array_map('\trim', $lines)); + foreach ($lines as $line) { + $pieces = \explode(' ', $line); + + switch (\count($pieces)) { + case 2: + $start = (int) $pieces[0]; + break; + + case 3: + switch ($pieces[2]) { + case 'n': + $offsets[$start] = [(int) $pieces[0], (int) $pieces[1]]; + $start++; + break 2; + case 'f': + $start++; + break 2; + } + // fall through if pieces doesn't match + + default: + throw new CrossReferenceException( + \sprintf('Unexpected data in xref table (%s)', \implode(' ', $pieces)), + CrossReferenceException::INVALID_DATA + ); + } + } + + $this->offsets = $offsets; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php new file mode 100644 index 000000000..a98fb1352 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/CrossReference/ReaderInterface.php @@ -0,0 +1,34 @@ + + if ($ch === 126 && isset($data[$k + 1]) && (\ord($data[$k + 1]) & 0xFF) === 62) { + break; + } + + if ($ch === 122 /* z */ && $state === 0) { + $out .= \chr(0) . \chr(0) . \chr(0) . \chr(0); + continue; + } + + if ($ch < 33 /* ! */ || $ch > 117 /* u */) { + throw new Ascii85Exception( + 'Illegal character found while ASCII85 decode.', + Ascii85Exception::ILLEGAL_CHAR_FOUND + ); + } + + $chn[$state] = $ch - 33;/* ! */ + $state++; + + if ($state === 5) { + $state = 0; + $r = 0; + for ($j = 0; $j < 5; ++$j) { + /** @noinspection UnnecessaryCastingInspection */ + $r = (int)($r * 85 + $chn[$j]); + } + + $out .= \chr($r >> 24) + . \chr($r >> 16) + . \chr($r >> 8) + . \chr($r); + } + } + + if ($state === 1) { + throw new Ascii85Exception( + 'Illegal length while ASCII85 decode.', + Ascii85Exception::ILLEGAL_LENGTH + ); + } + + if ($state === 2) { + $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1] + 1) * 85 * 85 * 85; + $out .= \chr($r >> 24); + } elseif ($state === 3) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2] + 1) * 85 * 85; + $out .= \chr($r >> 24); + $out .= \chr($r >> 16); + } elseif ($state === 4) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3] + 1) * 85; + $out .= \chr($r >> 24); + $out .= \chr($r >> 16); + $out .= \chr($r >> 8); + } + + return $out; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php b/src/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php new file mode 100644 index 000000000..e37eaa7d9 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Filter/Ascii85Exception.php @@ -0,0 +1,27 @@ +')); + if ((\strlen($data) % 2) === 1) { + $data .= '0'; + } + + return \pack('H*', $data); + } + + /** + * Converts a string into ASCII hexadecimal representation. + * + * @param string $data The input string + * @param boolean $leaveEOD + * @return string + */ + public function encode($data, $leaveEOD = false) + { + $t = \unpack('H*', $data); + return \current($t) + . ($leaveEOD ? '' : '>'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php b/src/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php new file mode 100644 index 000000000..18a07ce00 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Filter/FilterException.php @@ -0,0 +1,23 @@ +extensionLoaded()) { + $oData = $data; + $data = (($data !== '') ? @\gzuncompress($data) : ''); + if ($data === false) { + // let's try if the checksum is CRC32 + $fh = fopen('php://temp', 'w+b'); + fwrite($fh, "\x1f\x8b\x08\x00\x00\x00\x00\x00" . $oData); + // "window" == 31 -> 16 + (8 to 15): Uses the low 4 bits of the value as the window size logarithm. + // The input must include a gzip header and trailer (via 16). + stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 31]); + fseek($fh, 0); + $data = @stream_get_contents($fh); + fclose($fh); + + if ($data) { + return $data; + } + + // Try this fallback (remove the zlib stream header) + $data = @(gzinflate(substr($oData, 2))); + + if ($data === false) { + throw new FlateException( + 'Error while decompressing stream.', + FlateException::DECOMPRESS_ERROR + ); + } + } + } else { + throw new FlateException( + 'To handle FlateDecode filter, enable zlib support in PHP.', + FlateException::NO_ZLIB + ); + } + + return $data; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php b/src/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php new file mode 100644 index 000000000..aa3a2b397 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Filter/FlateException.php @@ -0,0 +1,27 @@ +initsTable(); + + $this->data = $data; + $this->dataLength = \strlen($data); + + // Initialize pointers + $this->bytePointer = 0; + + $this->nextData = 0; + $this->nextBits = 0; + + $prevCode = 0; + + $uncompData = ''; + + while (($code = $this->getNextCode()) !== 257) { + if ($code === 256) { + $this->initsTable(); + } elseif ($prevCode === 256) { + $uncompData .= $this->sTable[$code]; + } elseif ($code < $this->tIdx) { + $string = $this->sTable[$code]; + $uncompData .= $string; + + $this->addStringToTable($this->sTable[$prevCode], $string[0]); + } else { + $string = $this->sTable[$prevCode]; + $string .= $string[0]; + $uncompData .= $string; + + $this->addStringToTable($string); + } + $prevCode = $code; + } + + return $uncompData; + } + + /** + * Initialize the string table. + */ + protected function initsTable() + { + $this->sTable = []; + + for ($i = 0; $i < 256; $i++) { + $this->sTable[$i] = \chr($i); + } + + $this->tIdx = 258; + $this->bitsToGet = 9; + } + + /** + * Add a new string to the string table. + * + * @param string $oldString + * @param string $newString + */ + protected function addStringToTable($oldString, $newString = '') + { + $string = $oldString . $newString; + + // Add this new String to the table + $this->sTable[$this->tIdx++] = $string; + + if ($this->tIdx === 511) { + $this->bitsToGet = 10; + } elseif ($this->tIdx === 1023) { + $this->bitsToGet = 11; + } elseif ($this->tIdx === 2047) { + $this->bitsToGet = 12; + } + } + + /** + * Returns the next 9, 10, 11 or 12 bits. + * + * @return int + */ + protected function getNextCode() + { + if ($this->bytePointer === $this->dataLength) { + return 257; + } + + $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff); + $this->nextBits += 8; + + if ($this->nextBits < $this->bitsToGet) { + $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff); + $this->nextBits += 8; + } + + $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet - 9]; + $this->nextBits -= $this->bitsToGet; + + return $code; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php b/src/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php new file mode 100644 index 000000000..297edacd4 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Filter/LzwException.php @@ -0,0 +1,22 @@ +streamReader = $streamReader; + $this->tokenizer = new Tokenizer($streamReader); + } + + /** + * Removes cycled references. + * + * @internal + */ + public function cleanUp() + { + $this->xref = null; + } + + /** + * Get the stream reader instance. + * + * @return StreamReader + */ + public function getStreamReader() + { + return $this->streamReader; + } + + /** + * Get the tokenizer instance. + * + * @return Tokenizer + */ + public function getTokenizer() + { + return $this->tokenizer; + } + + /** + * Resolves the file header. + * + * @throws PdfParserException + * @return int + */ + protected function resolveFileHeader() + { + if ($this->fileHeader) { + return $this->fileHeaderOffset; + } + + $this->streamReader->reset(0); + $maxIterations = 1000; + while (true) { + $buffer = $this->streamReader->getBuffer(false); + $offset = \strpos($buffer, '%PDF-'); + if ($offset === false) { + if (!$this->streamReader->increaseLength(100) || (--$maxIterations === 0)) { + throw new PdfParserException( + 'Unable to find PDF file header.', + PdfParserException::FILE_HEADER_NOT_FOUND + ); + } + continue; + } + break; + } + + $this->fileHeaderOffset = $offset; + $this->streamReader->setOffset($offset); + + $this->fileHeader = \trim($this->streamReader->readLine()); + return $this->fileHeaderOffset; + } + + /** + * Get the cross-reference instance. + * + * @return CrossReference + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function getCrossReference() + { + if ($this->xref === null) { + $this->xref = new CrossReference($this, $this->resolveFileHeader()); + } + + return $this->xref; + } + + /** + * Get the PDF version. + * + * @return int[] An array of major and minor version. + * @throws PdfParserException + */ + public function getPdfVersion() + { + $this->resolveFileHeader(); + + if (\preg_match('/%PDF-(\d)\.(\d)/', $this->fileHeader, $result) === 0) { + throw new PdfParserException( + 'Unable to extract PDF version from file header.', + PdfParserException::PDF_VERSION_NOT_FOUND + ); + } + list(, $major, $minor) = $result; + + $catalog = $this->getCatalog(); + if (isset($catalog->value['Version'])) { + $versionParts = \explode( + '.', + PdfName::unescape(PdfType::resolve($catalog->value['Version'], $this)->value) + ); + if (count($versionParts) === 2) { + list($major, $minor) = $versionParts; + } + } + + return [(int) $major, (int) $minor]; + } + + /** + * Get the catalog dictionary. + * + * @return PdfDictionary + * @throws Type\PdfTypeException + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function getCatalog() + { + $trailer = $this->getCrossReference()->getTrailer(); + + $catalog = PdfType::resolve(PdfDictionary::get($trailer, 'Root'), $this); + + return PdfDictionary::ensure($catalog); + } + + /** + * Get an indirect object by its object number. + * + * @param int $objectNumber + * @param bool $cache + * @return PdfIndirectObject + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function getIndirectObject($objectNumber, $cache = false) + { + $objectNumber = (int) $objectNumber; + if (isset($this->objects[$objectNumber])) { + return $this->objects[$objectNumber]; + } + + $object = $this->getCrossReference()->getIndirectObject($objectNumber); + + if ($cache) { + $this->objects[$objectNumber] = $object; + } + + return $object; + } + + /** + * Read a PDF value. + * + * @param null|bool|string $token + * @param null|string $expectedType + * @return false|PdfArray|PdfBoolean|PdfDictionary|PdfHexString|PdfIndirectObject|PdfIndirectObjectReference|PdfName|PdfNull|PdfNumeric|PdfStream|PdfString|PdfToken + * @throws Type\PdfTypeException + */ + public function readValue($token = null, $expectedType = null) + { + if ($token === null) { + $token = $this->tokenizer->getNextToken(); + } + + if ($token === false) { + if ($expectedType !== null) { + throw new Type\PdfTypeException('Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE); + } + return false; + } + + switch ($token) { + case '(': + $this->ensureExpectedType($token, $expectedType); + return $this->parsePdfString(); + + case '<': + if ($this->streamReader->getByte() === '<') { + $this->ensureExpectedType('<<', $expectedType); + $this->streamReader->addOffset(1); + return $this->parsePdfDictionary(); + } + + $this->ensureExpectedType($token, $expectedType); + return $this->parsePdfHexString(); + + case '/': + $this->ensureExpectedType($token, $expectedType); + return $this->parsePdfName(); + + case '[': + $this->ensureExpectedType($token, $expectedType); + return $this->parsePdfArray(); + + default: + if (\is_numeric($token)) { + $token2 = $this->tokenizer->getNextToken(); + if ($token2 !== false) { + if (\is_numeric($token2)) { + $token3 = $this->tokenizer->getNextToken(); + if ($token3 === 'obj') { + if ($expectedType !== null && $expectedType !== PdfIndirectObject::class) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE + ); + } + + return $this->parsePdfIndirectObject((int) $token, (int) $token2); + } elseif ($token3 === 'R') { + if ( + $expectedType !== null && + $expectedType !== PdfIndirectObjectReference::class + ) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE + ); + } + + return PdfIndirectObjectReference::create((int) $token, (int) $token2); + } elseif ($token3 !== false) { + $this->tokenizer->pushStack($token3); + } + } + + $this->tokenizer->pushStack($token2); + } + + if ($expectedType !== null && $expectedType !== PdfNumeric::class) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE + ); + } + return PdfNumeric::create($token + 0); + } + + if ($token === 'true' || $token === 'false') { + $this->ensureExpectedType($token, $expectedType); + return PdfBoolean::create($token === 'true'); + } + + if ($token === 'null') { + $this->ensureExpectedType($token, $expectedType); + return new PdfNull(); + } + + if ($expectedType !== null && $expectedType !== PdfToken::class) { + throw new Type\PdfTypeException( + 'Got unexpected token type.', + Type\PdfTypeException::INVALID_DATA_TYPE + ); + } + + $v = new PdfToken(); + $v->value = $token; + + return $v; + } + } + + /** + * @return PdfString + */ + protected function parsePdfString() + { + return PdfString::parse($this->streamReader); + } + + /** + * @return false|PdfHexString + */ + protected function parsePdfHexString() + { + return PdfHexString::parse($this->streamReader); + } + + /** + * @return bool|PdfDictionary + * @throws PdfTypeException + */ + protected function parsePdfDictionary() + { + return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this); + } + + /** + * @return PdfName + */ + protected function parsePdfName() + { + return PdfName::parse($this->tokenizer, $this->streamReader); + } + + /** + * @return false|PdfArray + * @throws PdfTypeException + */ + protected function parsePdfArray() + { + return PdfArray::parse($this->tokenizer, $this); + } + + /** + * @param int $objectNumber + * @param int $generationNumber + * @return false|PdfIndirectObject + * @throws Type\PdfTypeException + */ + protected function parsePdfIndirectObject($objectNumber, $generationNumber) + { + return PdfIndirectObject::parse( + $objectNumber, + $generationNumber, + $this, + $this->tokenizer, + $this->streamReader + ); + } + + /** + * Ensures that the token will evaluate to an expected object type (or not). + * + * @param string $token + * @param string|null $expectedType + * @return bool + * @throws Type\PdfTypeException + */ + protected function ensureExpectedType($token, $expectedType) + { + static $mapping = [ + '(' => PdfString::class, + '<' => PdfHexString::class, + '<<' => PdfDictionary::class, + '/' => PdfName::class, + '[' => PdfArray::class, + 'true' => PdfBoolean::class, + 'false' => PdfBoolean::class, + 'null' => PdfNull::class + ]; + + if ($expectedType === null || $mapping[$token] === $expectedType) { + return true; + } + + throw new Type\PdfTypeException('Got unexpected token type.', Type\PdfTypeException::INVALID_DATA_TYPE); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php b/src/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php new file mode 100644 index 000000000..b2264ab34 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/PdfParserException.php @@ -0,0 +1,49 @@ +stream = $stream; + $this->closeStream = $closeStream; + $this->reset(); + } + + /** + * The destructor. + */ + public function __destruct() + { + $this->cleanUp(); + } + + /** + * Closes the file handle. + */ + public function cleanUp() + { + if ($this->closeStream && is_resource($this->stream)) { + \fclose($this->stream); + } + } + + /** + * Returns the byte length of the buffer. + * + * @param bool $atOffset + * @return int + */ + public function getBufferLength($atOffset = false) + { + if ($atOffset === false) { + return $this->bufferLength; + } + + return $this->bufferLength - $this->offset; + } + + /** + * Get the current position in the stream. + * + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * Returns the current buffer. + * + * @param bool $atOffset + * @return string + */ + public function getBuffer($atOffset = true) + { + if ($atOffset === false) { + return $this->buffer; + } + + $string = \substr($this->buffer, $this->offset); + + return (string) $string; + } + + /** + * Gets a byte at a specific position in the buffer. + * + * If the position is invalid the method will return false. + * + * If the $position parameter is set to null the value of $this->offset will be used. + * + * @param int|null $position + * @return string|bool + */ + public function getByte($position = null) + { + $position = (int) ($position !== null ? $position : $this->offset); + if ( + $position >= $this->bufferLength + && (!$this->increaseLength() || $position >= $this->bufferLength) + ) { + return false; + } + + return $this->buffer[$position]; + } + + /** + * Returns a byte at a specific position, and set the offset to the next byte position. + * + * If the position is invalid the method will return false. + * + * If the $position parameter is set to null the value of $this->offset will be used. + * + * @param int|null $position + * @return string|bool + */ + public function readByte($position = null) + { + if ($position !== null) { + $position = (int) $position; + // check if needed bytes are available in the current buffer + if (!($position >= $this->position && $position < $this->position + $this->bufferLength)) { + $this->reset($position); + $offset = $this->offset; + } else { + $offset = $position - $this->position; + } + } else { + $offset = $this->offset; + } + + if ( + $offset >= $this->bufferLength + && ((!$this->increaseLength()) || $offset >= $this->bufferLength) + ) { + return false; + } + + $this->offset = $offset + 1; + return $this->buffer[$offset]; + } + + /** + * Read bytes from the current or a specific offset position and set the internal pointer to the next byte. + * + * If the position is invalid the method will return false. + * + * If the $position parameter is set to null the value of $this->offset will be used. + * + * @param int $length + * @param int|null $position + * @return string|false + */ + public function readBytes($length, $position = null) + { + $length = (int) $length; + if ($position !== null) { + // check if needed bytes are available in the current buffer + if (!($position >= $this->position && $position < $this->position + $this->bufferLength)) { + $this->reset($position, $length); + $offset = $this->offset; + } else { + $offset = $position - $this->position; + } + } else { + $offset = $this->offset; + } + + if ( + ($offset + $length) > $this->bufferLength + && ((!$this->increaseLength($length)) || ($offset + $length) > $this->bufferLength) + ) { + return false; + } + + $bytes = \substr($this->buffer, $offset, $length); + $this->offset = $offset + $length; + + return $bytes; + } + + /** + * Read a line from the current position. + * + * @param int $length + * @return string|bool + */ + public function readLine($length = 1024) + { + if ($this->ensureContent() === false) { + return false; + } + + $line = ''; + while ($this->ensureContent()) { + $char = $this->readByte(); + + if ($char === "\n") { + break; + } + + if ($char === "\r") { + if ($this->getByte() === "\n") { + $this->addOffset(1); + } + break; + } + + $line .= $char; + + if (\strlen($line) >= $length) { + break; + } + } + + return $line; + } + + /** + * Set the offset position in the current buffer. + * + * @param int $offset + */ + public function setOffset($offset) + { + if ($offset > $this->bufferLength || $offset < 0) { + throw new \OutOfRangeException( + \sprintf('Offset (%s) out of range (length: %s)', $offset, $this->bufferLength) + ); + } + + $this->offset = (int) $offset; + } + + /** + * Returns the current offset in the current buffer. + * + * @return int + */ + public function getOffset() + { + return $this->offset; + } + + /** + * Add an offset to the current offset. + * + * @param int $offset + */ + public function addOffset($offset) + { + $this->setOffset($this->offset + $offset); + } + + /** + * Make sure that there is at least one character beyond the current offset in the buffer. + * + * @return bool + */ + public function ensureContent() + { + while ($this->offset >= $this->bufferLength) { + if (!$this->increaseLength()) { + return false; + } + } + return true; + } + + /** + * Returns the stream. + * + * @return resource + */ + public function getStream() + { + return $this->stream; + } + + /** + * Gets the total available length. + * + * @return int + */ + public function getTotalLength() + { + if ($this->totalLength === null) { + $stat = \fstat($this->stream); + $this->totalLength = $stat['size']; + } + + return $this->totalLength; + } + + /** + * Resets the buffer to a position and re-read the buffer with the given length. + * + * If the $pos parameter is negative the start buffer position will be the $pos'th position from + * the end of the file. + * + * If the $pos parameter is negative and the absolute value is bigger then the totalLength of + * the file $pos will set to zero. + * + * @param int|null $pos Start position of the new buffer + * @param int $length Length of the new buffer. Mustn't be negative + */ + public function reset($pos = 0, $length = 200) + { + if ($pos === null) { + $pos = $this->position + $this->offset; + } elseif ($pos < 0) { + $pos = \max(0, $this->getTotalLength() + $pos); + } + + \fseek($this->stream, $pos); + + $this->position = $pos; + $this->offset = 0; + if ($length > 0) { + $this->buffer = (string) \fread($this->stream, $length); + } else { + $this->buffer = ''; + } + $this->bufferLength = \strlen($this->buffer); + + // If a stream wrapper is in use it is possible that + // length values > 8096 will be ignored, so use the + // increaseLength()-method to correct that behavior + if ($this->bufferLength < $length && $this->increaseLength($length - $this->bufferLength)) { + // increaseLength parameter is $minLength, so cut to have only the required bytes in the buffer + $this->buffer = (string) \substr($this->buffer, 0, $length); + $this->bufferLength = \strlen($this->buffer); + } + } + + /** + * Ensures bytes in the buffer with a specific length and location in the file. + * + * @param int $pos + * @param int $length + * @see reset() + */ + public function ensure($pos, $length) + { + if ( + $pos >= $this->position + && $pos < ($this->position + $this->bufferLength) + && ($this->position + $this->bufferLength) >= ($pos + $length) + ) { + $this->offset = $pos - $this->position; + } else { + $this->reset($pos, $length); + } + } + + /** + * Forcefully read more data into the buffer. + * + * @param int $minLength + * @return bool Returns false if the stream reaches the end + */ + public function increaseLength($minLength = 100) + { + $length = \max($minLength, 100); + + if (\feof($this->stream) || $this->getTotalLength() === $this->position + $this->bufferLength) { + return false; + } + + $newLength = $this->bufferLength + $length; + do { + $this->buffer .= \fread($this->stream, $newLength - $this->bufferLength); + $this->bufferLength = \strlen($this->buffer); + } while (($this->bufferLength !== $newLength) && !\feof($this->stream)); + + return true; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php b/src/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php new file mode 100644 index 000000000..889d036c6 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Tokenizer.php @@ -0,0 +1,151 @@ +streamReader = $streamReader; + } + + /** + * Get the stream reader instance. + * + * @return StreamReader + */ + public function getStreamReader() + { + return $this->streamReader; + } + + /** + * Clear the token stack. + */ + public function clearStack() + { + $this->stack = []; + } + + /** + * Push a token onto the stack. + * + * @param string $token + */ + public function pushStack($token) + { + $this->stack[] = $token; + } + + /** + * Get next token. + * + * @return false|string + */ + public function getNextToken() + { + $token = \array_pop($this->stack); + if ($token !== null) { + return $token; + } + + if (($byte = $this->streamReader->readByte()) === false) { + return false; + } + + if (\in_array($byte, ["\x20", "\x0A", "\x0D", "\x0C", "\x09", "\x00"], true)) { + if ($this->leapWhiteSpaces() === false) { + return false; + } + $byte = $this->streamReader->readByte(); + } + + switch ($byte) { + case '/': + case '[': + case ']': + case '(': + case ')': + case '{': + case '}': + case '<': + case '>': + return $byte; + case '%': + $this->streamReader->readLine(); + return $this->getNextToken(); + } + + /* This way is faster than checking single bytes. + */ + $bufferOffset = $this->streamReader->getOffset(); + do { + $lastBuffer = $this->streamReader->getBuffer(false); + $pos = \strcspn( + $lastBuffer, + "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%", + $bufferOffset + ); + } while ( + // Break the loop if a delimiter or white space char is matched + // in the current buffer or increase the buffers length + $bufferOffset + $pos === \strlen($lastBuffer) + && $this->streamReader->increaseLength() + ); + + $result = \substr($lastBuffer, $bufferOffset - 1, $pos + 1); + $this->streamReader->setOffset($bufferOffset + $pos); + + return $result; + } + + /** + * Leap white spaces. + * + * @return boolean + */ + public function leapWhiteSpaces() + { + do { + if (!$this->streamReader->ensureContent()) { + return false; + } + + $buffer = $this->streamReader->getBuffer(false); + $matches = \strspn($buffer, "\x20\x0A\x0C\x0D\x09\x00", $this->streamReader->getOffset()); + if ($matches > 0) { + $this->streamReader->addOffset($matches); + } + } while ($this->streamReader->getOffset() >= $this->streamReader->getBufferLength()); + + return true; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php new file mode 100644 index 000000000..15f554977 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfArray.php @@ -0,0 +1,85 @@ +getNextToken()) !== ']') { + if ($token === false || ($value = $parser->readValue($token)) === false) { + return false; + } + + $result[] = $value; + } + + $v = new self(); + $v->value = $result; + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param PdfType[] $values + * @return self + */ + public static function create(array $values = []) + { + $v = new self(); + $v->value = $values; + + return $v; + } + + /** + * Ensures that the passed array is a PdfArray instance with a (optional) specific size. + * + * @param mixed $array + * @param null|int $size + * @return self + * @throws PdfTypeException + */ + public static function ensure($array, $size = null) + { + $result = PdfType::ensureType(self::class, $array, 'Array value expected.'); + + if ($size !== null && \count($array->value) !== $size) { + throw new PdfTypeException( + \sprintf('Array with %s entries expected.', $size), + PdfTypeException::INVALID_DATA_SIZE + ); + } + + return $result; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php new file mode 100644 index 000000000..3007a65f8 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfBoolean.php @@ -0,0 +1,42 @@ +value = (bool) $value; + return $v; + } + + /** + * Ensures that the passed value is a PdfBoolean instance. + * + * @param mixed $value + * @return self + * @throws PdfTypeException + */ + public static function ensure($value) + { + return PdfType::ensureType(self::class, $value, 'Boolean value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php new file mode 100644 index 000000000..f43dc071d --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfDictionary.php @@ -0,0 +1,136 @@ +getNextToken(); + if ($token === '>' && $streamReader->getByte() === '>') { + $streamReader->addOffset(1); + break; + } + + $key = $parser->readValue($token); + if ($key === false) { + return false; + } + + // ensure the first value to be a Name object + if (!($key instanceof PdfName)) { + $lastToken = null; + // ignore all other entries and search for the closing brackets + while (($token = $tokenizer->getNextToken()) !== '>' || $lastToken !== '>') { + if ($token === false) { + return false; + } + $lastToken = $token; + } + + break; + } + + + $value = $parser->readValue(); + if ($value === false) { + return false; + } + + if ($value instanceof PdfNull) { + continue; + } + + // catch missing value + if ($value instanceof PdfToken && $value->value === '>' && $streamReader->getByte() === '>') { + $streamReader->addOffset(1); + break; + } + + $entries[$key->value] = $value; + } + + $v = new self(); + $v->value = $entries; + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param PdfType[] $entries The keys are the name entries of the dictionary. + * @return self + */ + public static function create(array $entries = []) + { + $v = new self(); + $v->value = $entries; + + return $v; + } + + /** + * Get a value by its key from a dictionary or a default value. + * + * @param mixed $dictionary + * @param string $key + * @param PdfType|null $default + * @return PdfNull|PdfType + * @throws PdfTypeException + */ + public static function get($dictionary, $key, $default = null) + { + if ($default !== null && !($default instanceof PdfType)) { + throw new \InvalidArgumentException('Default value must be an instance of PdfType or null'); + } + $dictionary = self::ensure($dictionary); + + if (isset($dictionary->value[$key])) { + return $dictionary->value[$key]; + } + + return $default === null + ? new PdfNull() + : $default; + } + + /** + * Ensures that the passed value is a PdfDictionary instance. + * + * @param mixed $dictionary + * @return self + * @throws PdfTypeException + */ + public static function ensure($dictionary) + { + return PdfType::ensureType(self::class, $dictionary, 'Dictionary value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php new file mode 100644 index 000000000..309706b34 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfHexString.php @@ -0,0 +1,77 @@ +getOffset(); + + while (true) { + $buffer = $streamReader->getBuffer(false); + $pos = \strpos($buffer, '>', $bufferOffset); + if ($pos === false) { + if (!$streamReader->increaseLength()) { + return false; + } + continue; + } + + break; + } + + $result = \substr($buffer, $bufferOffset, $pos - $bufferOffset); + $streamReader->setOffset($pos + 1); + + $v = new self(); + $v->value = $result; + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param string $string The hex encoded string. + * @return self + */ + public static function create($string) + { + $v = new self(); + $v->value = $string; + + return $v; + } + + /** + * Ensures that the passed value is a PdfHexString instance. + * + * @param mixed $hexString + * @return self + * @throws PdfTypeException + */ + public static function ensure($hexString) + { + return PdfType::ensureType(self::class, $hexString, 'Hex string value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php new file mode 100644 index 000000000..ce51d48d5 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObject.php @@ -0,0 +1,103 @@ +readValue(); + if ($value === false) { + return false; + } + + $nextToken = $tokenizer->getNextToken(); + if ($nextToken === 'stream') { + $value = PdfStream::parse($value, $reader, $parser); + } elseif ($nextToken !== false) { + $tokenizer->pushStack($nextToken); + } + + $v = new self(); + $v->objectNumber = (int) $objectNumber; + $v->generationNumber = (int) $objectGenerationNumber; + $v->value = $value; + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param int $objectNumber + * @param int $generationNumber + * @param PdfType $value + * @return self + */ + public static function create($objectNumber, $generationNumber, PdfType $value) + { + $v = new self(); + $v->objectNumber = (int) $objectNumber; + $v->generationNumber = (int) $generationNumber; + $v->value = $value; + + return $v; + } + + /** + * Ensures that the passed value is a PdfIndirectObject instance. + * + * @param mixed $indirectObject + * @return self + * @throws PdfTypeException + */ + public static function ensure($indirectObject) + { + return PdfType::ensureType(self::class, $indirectObject, 'Indirect object expected.'); + } + + /** + * The object number. + * + * @var int + */ + public $objectNumber; + + /** + * The generation number. + * + * @var int + */ + public $generationNumber; +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php new file mode 100644 index 000000000..1ace37843 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfIndirectObjectReference.php @@ -0,0 +1,52 @@ +value = (int) $objectNumber; + $v->generationNumber = (int) $generationNumber; + + return $v; + } + + /** + * Ensures that the passed value is a PdfIndirectObject instance. + * + * @param mixed $value + * @return self + * @throws PdfTypeException + */ + public static function ensure($value) + { + return PdfType::ensureType(self::class, $value, 'Indirect reference value expected.'); + } + + /** + * The generation number. + * + * @var int + */ + public $generationNumber; +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php new file mode 100644 index 000000000..3732aecc0 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfName.php @@ -0,0 +1,82 @@ +getByte(), "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%") === 0) { + $v->value = (string) $tokenizer->getNextToken(); + return $v; + } + + $v->value = ''; + return $v; + } + + /** + * Unescapes a name string. + * + * @param string $value + * @return string + */ + public static function unescape($value) + { + if (strpos($value, '#') === false) { + return $value; + } + + return preg_replace_callback('/#([a-fA-F\d]{2})/', function ($matches) { + return chr(hexdec($matches[1])); + }, $value); + } + + /** + * Helper method to create an instance. + * + * @param string $string + * @return self + */ + public static function create($string) + { + $v = new self(); + $v->value = $string; + + return $v; + } + + /** + * Ensures that the passed value is a PdfName instance. + * + * @param mixed $name + * @return self + * @throws PdfTypeException + */ + public static function ensure($name) + { + return PdfType::ensureType(self::class, $name, 'Name value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php new file mode 100644 index 000000000..7aef36330 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfNull.php @@ -0,0 +1,19 @@ +value = $value + 0; + + return $v; + } + + /** + * Ensures that the passed value is a PdfNumeric instance. + * + * @param mixed $value + * @return self + * @throws PdfTypeException + */ + public static function ensure($value) + { + return PdfType::ensureType(self::class, $value, 'Numeric value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php new file mode 100644 index 000000000..9edcd52f2 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfStream.php @@ -0,0 +1,355 @@ +value = $dictionary; + $v->reader = $reader; + $v->parser = $parser; + + $offset = $reader->getOffset(); + + // Find the first "newline" + while (($firstByte = $reader->getByte($offset)) !== false) { + $offset++; + if ($firstByte === "\n" || $firstByte === "\r") { + break; + } + } + + if ($firstByte === false) { + throw new PdfTypeException( + 'Unable to parse stream data. No newline after the stream keyword found.', + PdfTypeException::NO_NEWLINE_AFTER_STREAM_KEYWORD + ); + } + + $sndByte = $reader->getByte($offset); + if ($sndByte === "\n" && $firstByte !== "\n") { + $offset++; + } + + $reader->setOffset($offset); + // let's only save the byte-offset and read the stream only when needed + $v->stream = $reader->getPosition() + $reader->getOffset(); + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param PdfDictionary $dictionary + * @param string $stream + * @return self + */ + public static function create(PdfDictionary $dictionary, $stream) + { + $v = new self(); + $v->value = $dictionary; + $v->stream = (string) $stream; + + return $v; + } + + /** + * Ensures that the passed value is a PdfStream instance. + * + * @param mixed $stream + * @return self + * @throws PdfTypeException + */ + public static function ensure($stream) + { + return PdfType::ensureType(self::class, $stream, 'Stream value expected.'); + } + + /** + * The stream or its byte-offset position. + * + * @var int|string + */ + protected $stream; + + /** + * The stream reader instance. + * + * @var StreamReader|null + */ + protected $reader; + + /** + * The PDF parser instance. + * + * @var PdfParser + */ + protected $parser; + + /** + * Get the stream data. + * + * @param bool $cache Whether cache the stream data or not. + * @return bool|string + * @throws PdfTypeException + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function getStream($cache = false) + { + if (\is_int($this->stream)) { + $length = PdfDictionary::get($this->value, 'Length'); + if ($this->parser !== null) { + $length = PdfType::resolve($length, $this->parser); + } + + if (!($length instanceof PdfNumeric) || $length->value === 0) { + $this->reader->reset($this->stream, 100000); + $buffer = $this->extractStream(); + } else { + $this->reader->reset($this->stream, $length->value); + $buffer = $this->reader->getBuffer(false); + if ($this->parser !== null) { + $this->reader->reset($this->stream + strlen($buffer)); + $this->parser->getTokenizer()->clearStack(); + $token = $this->parser->readValue(); + if ($token === false || !($token instanceof PdfToken) || $token->value !== 'endstream') { + $this->reader->reset($this->stream, 100000); + $buffer = $this->extractStream(); + $this->reader->reset($this->stream + strlen($buffer)); + } + } + } + + if ($cache === false) { + return $buffer; + } + + $this->stream = $buffer; + $this->reader = null; + } + + return $this->stream; + } + + /** + * Extract the stream "manually". + * + * @return string + * @throws PdfTypeException + */ + protected function extractStream() + { + while (true) { + $buffer = $this->reader->getBuffer(false); + $length = \strpos($buffer, 'endstream'); + if ($length === false) { + if (!$this->reader->increaseLength(100000)) { + throw new PdfTypeException('Cannot extract stream.'); + } + continue; + } + break; + } + + $buffer = \substr($buffer, 0, $length); + $lastByte = \substr($buffer, -1); + + /* Check for EOL marker = + * CARRIAGE RETURN (\r) and a LINE FEED (\n) or just a LINE FEED (\n}, + * and not by a CARRIAGE RETURN (\r) alone + */ + if ($lastByte === "\n") { + $buffer = \substr($buffer, 0, -1); + + $lastByte = \substr($buffer, -1); + if ($lastByte === "\r") { + $buffer = \substr($buffer, 0, -1); + } + } + + // There are streams in the wild, which have only white signs in them but need to be parsed manually due + // to a problem encountered before (e.g. Length === 0). We should set them to empty streams to avoid problems + // in further processing (e.g. applying of filters). + if (trim($buffer) === '') { + $buffer = ''; + } + + return $buffer; + } + + /** + * Get all filters defined for this stream. + * + * @return PdfType[] + * @throws PdfTypeException + */ + public function getFilters() + { + $filters = PdfDictionary::get($this->value, 'Filter'); + if ($filters instanceof PdfNull) { + return []; + } + + if ($filters instanceof PdfArray) { + $filters = $filters->value; + } else { + $filters = [$filters]; + } + + return $filters; + } + + /** + * Get the unfiltered stream data. + * + * @return string + * @throws FilterException + * @throws PdfParserException + */ + public function getUnfilteredStream() + { + $stream = $this->getStream(); + $filters = $this->getFilters(); + if ($filters === []) { + return $stream; + } + + $decodeParams = PdfDictionary::get($this->value, 'DecodeParms'); + if ($decodeParams instanceof PdfArray) { + $decodeParams = $decodeParams->value; + } else { + $decodeParams = [$decodeParams]; + } + + foreach ($filters as $key => $filter) { + if (!($filter instanceof PdfName)) { + continue; + } + + $decodeParam = null; + if (isset($decodeParams[$key])) { + $decodeParam = ($decodeParams[$key] instanceof PdfDictionary ? $decodeParams[$key] : null); + } + + switch ($filter->value) { + case 'FlateDecode': + case 'Fl': + case 'LZWDecode': + case 'LZW': + if (\strpos($filter->value, 'LZW') === 0) { + $filterObject = new Lzw(); + } else { + $filterObject = new Flate(); + } + + $stream = $filterObject->decode($stream); + + if ($decodeParam instanceof PdfDictionary) { + $predictor = PdfDictionary::get($decodeParam, 'Predictor', PdfNumeric::create(1)); + if ($predictor->value !== 1) { + if (!\class_exists(Predictor::class)) { + throw new PdfParserException( + 'This PDF document makes use of features which are only implemented in the ' . + 'commercial "FPDI PDF-Parser" add-on (see https://www.setasign.com/fpdi-pdf-' . + 'parser).', + PdfParserException::IMPLEMENTED_IN_FPDI_PDF_PARSER + ); + } + + $colors = PdfDictionary::get($decodeParam, 'Colors', PdfNumeric::create(1)); + $bitsPerComponent = PdfDictionary::get( + $decodeParam, + 'BitsPerComponent', + PdfNumeric::create(8) + ); + + $columns = PdfDictionary::get($decodeParam, 'Columns', PdfNumeric::create(1)); + + $filterObject = new Predictor( + $predictor->value, + $colors->value, + $bitsPerComponent->value, + $columns->value + ); + + $stream = $filterObject->decode($stream); + } + } + + break; + case 'ASCII85Decode': + case 'A85': + $filterObject = new Ascii85(); + $stream = $filterObject->decode($stream); + break; + + case 'ASCIIHexDecode': + case 'AHx': + $filterObject = new AsciiHex(); + $stream = $filterObject->decode($stream); + break; + + case 'Crypt': + if (!$decodeParam instanceof PdfDictionary) { + break; + } + // Filter is "Identity" + $name = PdfDictionary::get($decodeParam, 'Name'); + if (!$name instanceof PdfName || $name->value !== 'Identity') { + break; + } + + throw new FilterException( + 'Support for Crypt filters other than "Identity" is not implemented.', + FilterException::UNSUPPORTED_FILTER + ); + + default: + throw new FilterException( + \sprintf('Unsupported filter "%s".', $filter->value), + FilterException::UNSUPPORTED_FILTER + ); + } + } + + return $stream; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php new file mode 100644 index 000000000..89b90c5d9 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfString.php @@ -0,0 +1,202 @@ +getOffset(); + $openBrackets = 1; + do { + $buffer = $streamReader->getBuffer(false); + for ($length = \strlen($buffer); $openBrackets !== 0 && $pos < $length; $pos++) { + switch ($buffer[$pos]) { + case '(': + $openBrackets++; + break; + case ')': + $openBrackets--; + break; + case '\\': + $pos++; + } + } + } while ($openBrackets !== 0 && $streamReader->increaseLength()); + + $result = \substr($buffer, $startPos, $openBrackets + $pos - $startPos - 1); + $streamReader->setOffset($pos); + + $v = new self(); + $v->value = $result; + + return $v; + } + + /** + * Helper method to create an instance. + * + * @param string $value The string needs to be escaped accordingly. + * @return self + */ + public static function create($value) + { + $v = new self(); + $v->value = $value; + + return $v; + } + + /** + * Ensures that the passed value is a PdfString instance. + * + * @param mixed $string + * @return self + * @throws PdfTypeException + */ + public static function ensure($string) + { + return PdfType::ensureType(self::class, $string, 'String value expected.'); + } + + /** + * Escapes sequences in a string according to the PDF specification. + * + * @param string $s + * @return string + */ + public static function escape($s) + { + // Still a bit faster, than direct replacing + if ( + \strpos($s, '\\') !== false || + \strpos($s, ')') !== false || + \strpos($s, '(') !== false || + \strpos($s, "\x0D") !== false || + \strpos($s, "\x0A") !== false || + \strpos($s, "\x09") !== false || + \strpos($s, "\x08") !== false || + \strpos($s, "\x0C") !== false + ) { + // is faster than strtr(...) + return \str_replace( + ['\\', ')', '(', "\x0D", "\x0A", "\x09", "\x08", "\x0C"], + ['\\\\', '\\)', '\\(', '\r', '\n', '\t', '\b', '\f'], + $s + ); + } + + return $s; + } + + /** + * Unescapes escaped sequences in a PDF string according to the PDF specification. + * + * @param string $s + * @return string + */ + public static function unescape($s) + { + $out = ''; + /** @noinspection ForeachInvariantsInspection */ + for ($count = 0, $n = \strlen($s); $count < $n; $count++) { + if ($s[$count] !== '\\') { + $out .= $s[$count]; + } else { + // A backslash at the end of the string - ignore it + if ($count === ($n - 1)) { + break; + } + + switch ($s[++$count]) { + case ')': + case '(': + case '\\': + $out .= $s[$count]; + break; + + case 'f': + $out .= "\x0C"; + break; + + case 'b': + $out .= "\x08"; + break; + + case 't': + $out .= "\x09"; + break; + + case 'r': + $out .= "\x0D"; + break; + + case 'n': + $out .= "\x0A"; + break; + + case "\r": + if ($count !== $n - 1 && $s[$count + 1] === "\n") { + $count++; + } + break; + + case "\n": + break; + + default: + $actualChar = \ord($s[$count]); + // ascii 48 = number 0 + // ascii 57 = number 9 + if ($actualChar >= 48 && $actualChar <= 57) { + $oct = '' . $s[$count]; + + /** @noinspection NotOptimalIfConditionsInspection */ + if ( + $count + 1 < $n + && \ord($s[$count + 1]) >= 48 + && \ord($s[$count + 1]) <= 57 + ) { + $count++; + $oct .= $s[$count]; + + /** @noinspection NotOptimalIfConditionsInspection */ + if ( + $count + 1 < $n + && \ord($s[$count + 1]) >= 48 + && \ord($s[$count + 1]) <= 57 + ) { + $oct .= $s[++$count]; + } + } + + $out .= \chr(\octdec($oct)); + } else { + // If the character is not one of those defined, the backslash is ignored + $out .= $s[$count]; + } + } + } + } + return $out; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php new file mode 100644 index 000000000..a0de203e8 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfToken.php @@ -0,0 +1,43 @@ +value = $token; + + return $v; + } + + /** + * Ensures that the passed value is a PdfToken instance. + * + * @param mixed $token + * @return self + * @throws PdfTypeException + */ + public static function ensure($token) + { + return PdfType::ensureType(self::class, $token, 'Token value expected.'); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php new file mode 100644 index 000000000..5330a44c7 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfType.php @@ -0,0 +1,106 @@ +value, $parser, $stopAtIndirectObject); + } + + if ($value instanceof PdfIndirectObjectReference) { + return self::resolve($parser->getIndirectObject($value->value), $parser, $stopAtIndirectObject); + } + + return $value; + } + + /** + * Ensure that a value is an instance of a specific PDF type. + * + * @param string $type + * @param PdfType $value + * @param string $errorMessage + * @return mixed + * @throws PdfTypeException + */ + protected static function ensureType($type, $value, $errorMessage) + { + if (!($value instanceof $type)) { + throw new PdfTypeException( + $errorMessage, + PdfTypeException::INVALID_DATA_TYPE + ); + } + + return $value; + } + + /** + * Flatten indirect object references to direct objects. + * + * @param PdfType $value + * @param PdfParser $parser + * @return PdfType + * @throws CrossReferenceException + * @throws PdfParserException + */ + public static function flatten(PdfType $value, PdfParser $parser) + { + if ($value instanceof PdfIndirectObjectReference) { + return self::flatten(self::resolve($value, $parser), $parser); + } + + if ($value instanceof PdfDictionary || $value instanceof PdfArray) { + foreach ($value->value as $key => $_value) { + $value->value[$key] = self::flatten($_value, $parser); + } + } + + if ($value instanceof PdfStream) { + throw new PdfTypeException('There is a stream object found which cannot be flattened to a direct object.'); + } + + return $value; + } + + /** + * The value of the PDF type. + * + * @var mixed + */ + public $value; +} diff --git a/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php new file mode 100644 index 000000000..3d2b93cdd --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfParser/Type/PdfTypeException.php @@ -0,0 +1,24 @@ +value; + $ax = PdfNumeric::ensure(PdfType::resolve($array[0], $parser))->value; + $ay = PdfNumeric::ensure(PdfType::resolve($array[1], $parser))->value; + $bx = PdfNumeric::ensure(PdfType::resolve($array[2], $parser))->value; + $by = PdfNumeric::ensure(PdfType::resolve($array[3], $parser))->value; + + return new self($ax, $ay, $bx, $by); + } + + public static function byVectors(Vector $ll, Vector $ur) + { + return new self($ll->getX(), $ll->getY(), $ur->getX(), $ur->getY()); + } + + /** + * Rectangle constructor. + * + * @param float|int $ax + * @param float|int $ay + * @param float|int $bx + * @param float|int $by + */ + public function __construct($ax, $ay, $bx, $by) + { + $this->llx = \min($ax, $bx); + $this->lly = \min($ay, $by); + $this->urx = \max($ax, $bx); + $this->ury = \max($ay, $by); + } + + /** + * Get the width of the rectangle. + * + * @return float|int + */ + public function getWidth() + { + return $this->urx - $this->llx; + } + + /** + * Get the height of the rectangle. + * + * @return float|int + */ + public function getHeight() + { + return $this->ury - $this->lly; + } + + /** + * Get the lower left abscissa. + * + * @return float|int + */ + public function getLlx() + { + return $this->llx; + } + + /** + * Get the lower left ordinate. + * + * @return float|int + */ + public function getLly() + { + return $this->lly; + } + + /** + * Get the upper right abscissa. + * + * @return float|int + */ + public function getUrx() + { + return $this->urx; + } + + /** + * Get the upper right ordinate. + * + * @return float|int + */ + public function getUry() + { + return $this->ury; + } + + /** + * Get the rectangle as an array. + * + * @return array + */ + public function toArray() + { + return [ + $this->llx, + $this->lly, + $this->urx, + $this->ury + ]; + } + + /** + * Get the rectangle as a PdfArray. + * + * @return PdfArray + */ + public function toPdfArray() + { + $array = new PdfArray(); + $array->value[] = PdfNumeric::create($this->llx); + $array->value[] = PdfNumeric::create($this->lly); + $array->value[] = PdfNumeric::create($this->urx); + $array->value[] = PdfNumeric::create($this->ury); + + return $array; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfReader/Page.php b/src/vendor/setasign/fpdi/src/PdfReader/Page.php new file mode 100644 index 000000000..c2463dd28 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfReader/Page.php @@ -0,0 +1,422 @@ +pageObject = $page; + $this->parser = $parser; + } + + /** + * Get the indirect object of this page. + * + * @return PdfIndirectObject + */ + public function getPageObject() + { + return $this->pageObject; + } + + /** + * Get the dictionary of this page. + * + * @return PdfDictionary + * @throws PdfParserException + * @throws PdfTypeException + * @throws CrossReferenceException + */ + public function getPageDictionary() + { + if ($this->pageDictionary === null) { + $this->pageDictionary = PdfDictionary::ensure(PdfType::resolve($this->getPageObject(), $this->parser)); + } + + return $this->pageDictionary; + } + + /** + * Get a page attribute. + * + * @param string $name + * @param bool $inherited + * @return PdfType|null + * @throws PdfParserException + * @throws PdfTypeException + * @throws CrossReferenceException + */ + public function getAttribute($name, $inherited = true) + { + $dict = $this->getPageDictionary(); + + if (isset($dict->value[$name])) { + return $dict->value[$name]; + } + + $inheritedKeys = ['Resources', 'MediaBox', 'CropBox', 'Rotate']; + if ($inherited && \in_array($name, $inheritedKeys, true)) { + if ($this->inheritedAttributes === null) { + $this->inheritedAttributes = []; + $inheritedKeys = \array_filter($inheritedKeys, function ($key) use ($dict) { + return !isset($dict->value[$key]); + }); + + if (\count($inheritedKeys) > 0) { + $parentDict = PdfType::resolve(PdfDictionary::get($dict, 'Parent'), $this->parser); + while ($parentDict instanceof PdfDictionary) { + foreach ($inheritedKeys as $index => $key) { + if (isset($parentDict->value[$key])) { + $this->inheritedAttributes[$key] = $parentDict->value[$key]; + unset($inheritedKeys[$index]); + } + } + + /** @noinspection NotOptimalIfConditionsInspection */ + if (isset($parentDict->value['Parent']) && \count($inheritedKeys) > 0) { + $parentDict = PdfType::resolve(PdfDictionary::get($parentDict, 'Parent'), $this->parser); + } else { + break; + } + } + } + } + + if (isset($this->inheritedAttributes[$name])) { + return $this->inheritedAttributes[$name]; + } + } + + return null; + } + + /** + * Get the rotation value. + * + * @return int + * @throws PdfParserException + * @throws PdfTypeException + * @throws CrossReferenceException + */ + public function getRotation() + { + $rotation = $this->getAttribute('Rotate'); + if ($rotation === null) { + return 0; + } + + $rotation = PdfNumeric::ensure(PdfType::resolve($rotation, $this->parser))->value % 360; + + if ($rotation < 0) { + $rotation += 360; + } + + return $rotation; + } + + /** + * Get a boundary of this page. + * + * @param string $box + * @param bool $fallback + * @return bool|Rectangle + * @throws PdfParserException + * @throws PdfTypeException + * @throws CrossReferenceException + * @see PageBoundaries + */ + public function getBoundary($box = PageBoundaries::CROP_BOX, $fallback = true) + { + $value = $this->getAttribute($box); + + if ($value !== null) { + return Rectangle::byPdfArray($value, $this->parser); + } + + if ($fallback === false) { + return false; + } + + switch ($box) { + case PageBoundaries::BLEED_BOX: + case PageBoundaries::TRIM_BOX: + case PageBoundaries::ART_BOX: + return $this->getBoundary(PageBoundaries::CROP_BOX, true); + case PageBoundaries::CROP_BOX: + return $this->getBoundary(PageBoundaries::MEDIA_BOX, true); + } + + return false; + } + + /** + * Get the width and height of this page. + * + * @param string $box + * @param bool $fallback + * @return array|bool + * @throws PdfParserException + * @throws PdfTypeException + * @throws CrossReferenceException + */ + public function getWidthAndHeight($box = PageBoundaries::CROP_BOX, $fallback = true) + { + $boundary = $this->getBoundary($box, $fallback); + if ($boundary === false) { + return false; + } + + $rotation = $this->getRotation(); + $interchange = ($rotation / 90) % 2; + + return [ + $interchange ? $boundary->getHeight() : $boundary->getWidth(), + $interchange ? $boundary->getWidth() : $boundary->getHeight() + ]; + } + + /** + * Get the raw content stream. + * + * @return string + * @throws PdfReaderException + * @throws PdfTypeException + * @throws FilterException + * @throws PdfParserException + */ + public function getContentStream() + { + $dict = $this->getPageDictionary(); + $contents = PdfType::resolve(PdfDictionary::get($dict, 'Contents'), $this->parser); + if ($contents instanceof PdfNull) { + return ''; + } + + if ($contents instanceof PdfArray) { + $result = []; + foreach ($contents->value as $content) { + $content = PdfType::resolve($content, $this->parser); + if (!($content instanceof PdfStream)) { + continue; + } + $result[] = $content->getUnfilteredStream(); + } + + return \implode("\n", $result); + } + + if ($contents instanceof PdfStream) { + return $contents->getUnfilteredStream(); + } + + throw new PdfReaderException( + 'Array or stream expected.', + PdfReaderException::UNEXPECTED_DATA_TYPE + ); + } + + /** + * Get information of all external links on this page. + * + * All coordinates are normalized in view to rotation and translation of the boundary-box, so that their + * origin is lower-left. + * + * The URI is the binary value of the PDF string object. It can be in PdfDocEncoding or in UTF-16BE encoding. + * + * @return array + */ + public function getExternalLinks($box = PageBoundaries::CROP_BOX) + { + try { + $dict = $this->getPageDictionary(); + $annotations = PdfType::resolve(PdfDictionary::get($dict, 'Annots'), $this->parser); + } catch (FpdiException $e) { + return []; + } + + if (!$annotations instanceof PdfArray) { + return []; + } + + $links = []; + + foreach ($annotations->value as $entry) { + try { + $annotation = PdfType::resolve($entry, $this->parser); + + $value = PdfType::resolve(PdfDictionary::get($annotation, 'Subtype'), $this->parser); + if (!$value instanceof PdfName || $value->value !== 'Link') { + continue; + } + + $dest = PdfType::resolve(PdfDictionary::get($annotation, 'Dest'), $this->parser); + if (!$dest instanceof PdfNull) { + continue; + } + + $action = PdfType::resolve(PdfDictionary::get($annotation, 'A'), $this->parser); + if (!$action instanceof PdfDictionary) { + continue; + } + + $actionType = PdfType::resolve(PdfDictionary::get($action, 'S'), $this->parser); + if (!$actionType instanceof PdfName || $actionType->value !== 'URI') { + continue; + } + + $uri = PdfType::resolve(PdfDictionary::get($action, 'URI'), $this->parser); + if ($uri instanceof PdfString) { + $uriValue = PdfString::unescape($uri->value); + } elseif ($uri instanceof PdfHexString) { + $uriValue = \hex2bin($uri->value); + } else { + continue; + } + + $rect = PdfType::resolve(PdfDictionary::get($annotation, 'Rect'), $this->parser); + if (!$rect instanceof PdfArray || count($rect->value) !== 4) { + continue; + } + + $rect = Rectangle::byPdfArray($rect, $this->parser); + if ($rect->getWidth() === 0 || $rect->getHeight() === 0) { + continue; + } + + $bbox = $this->getBoundary($box); + $rotation = $this->getRotation(); + + $gs = new GraphicsState(); + $gs->translate(-$bbox->getLlx(), -$bbox->getLly()); + $gs->rotate($bbox->getLlx(), $bbox->getLly(), -$rotation); + + switch ($rotation) { + case 90: + $gs->translate(-$bbox->getWidth(), 0); + break; + case 180: + $gs->translate(-$bbox->getWidth(), -$bbox->getHeight()); + break; + case 270: + $gs->translate(0, -$bbox->getHeight()); + break; + } + + $normalizedRect = Rectangle::byVectors( + $gs->toUserSpace(new Vector($rect->getLlx(), $rect->getLly())), + $gs->toUserSpace(new Vector($rect->getUrx(), $rect->getUry())) + ); + + $quadPoints = PdfType::resolve(PdfDictionary::get($annotation, 'QuadPoints'), $this->parser); + $normalizedQuadPoints = []; + if ($quadPoints instanceof PdfArray) { + $quadPointsCount = count($quadPoints->value); + if ($quadPointsCount % 8 === 0) { + for ($i = 0; ($i + 1) < $quadPointsCount; $i += 2) { + $x = PdfNumeric::ensure(PdfType::resolve($quadPoints->value[$i], $this->parser)); + $y = PdfNumeric::ensure(PdfType::resolve($quadPoints->value[$i + 1], $this->parser)); + + $v = $gs->toUserSpace(new Vector($x->value, $y->value)); + $normalizedQuadPoints[] = $v->getX(); + $normalizedQuadPoints[] = $v->getY(); + } + } + } + + // we remove unsupported/unneeded values here + unset( + $annotation->value['P'], + $annotation->value['NM'], + $annotation->value['AP'], + $annotation->value['AS'], + $annotation->value['Type'], + $annotation->value['Subtype'], + $annotation->value['Rect'], + $annotation->value['A'], + $annotation->value['QuadPoints'], + $annotation->value['Rotate'], + $annotation->value['M'], + $annotation->value['StructParent'], + $annotation->value['OC'] + ); + + // ...and flatten the PDF object to eliminate any indirect references. + // Indirect references are a problem when writing the output in FPDF + // because FPDF uses pre-calculated object numbers while FPDI creates + // them at runtime. + $annotation = PdfType::flatten($annotation, $this->parser); + + $links[] = [ + 'rect' => $normalizedRect, + 'quadPoints' => $normalizedQuadPoints, + 'uri' => $uriValue, + 'pdfObject' => $annotation + ]; + } catch (FpdiException $e) { + continue; + } + } + + return $links; + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php b/src/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php new file mode 100644 index 000000000..351542185 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfReader/PageBoundaries.php @@ -0,0 +1,94 @@ +parser = $parser; + } + + /** + * PdfReader destructor. + */ + public function __destruct() + { + if ($this->parser !== null) { + $this->parser->cleanUp(); + } + } + + /** + * Get the pdf parser instance. + * + * @return PdfParser + */ + public function getParser() + { + return $this->parser; + } + + /** + * Get the PDF version. + * + * @return string + * @throws PdfParserException + */ + public function getPdfVersion() + { + return \implode('.', $this->parser->getPdfVersion()); + } + + /** + * Get the page count. + * + * @return int + * @throws PdfTypeException + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function getPageCount() + { + if ($this->pageCount === null) { + $catalog = $this->parser->getCatalog(); + + $pages = PdfType::resolve(PdfDictionary::get($catalog, 'Pages'), $this->parser); + $count = PdfType::resolve(PdfDictionary::get($pages, 'Count'), $this->parser); + + $this->pageCount = PdfNumeric::ensure($count)->value; + } + + return $this->pageCount; + } + + /** + * Get a page instance. + * + * @param int|numeric-string $pageNumber + * @return Page + * @throws PdfTypeException + * @throws CrossReferenceException + * @throws PdfParserException + * @throws \InvalidArgumentException + */ + public function getPage($pageNumber) + { + if (!\is_numeric($pageNumber)) { + throw new \InvalidArgumentException( + 'Page number needs to be a number.' + ); + } + + if ($pageNumber < 1 || $pageNumber > $this->getPageCount()) { + throw new \InvalidArgumentException( + \sprintf( + 'Page number "%s" out of available page range (1 - %s)', + $pageNumber, + $this->getPageCount() + ) + ); + } + + $this->readPages(); + + $page = $this->pages[$pageNumber - 1]; + + if ($page instanceof PdfIndirectObjectReference) { + $readPages = function ($kids) use (&$readPages) { + $kids = PdfArray::ensure($kids); + + /** @noinspection LoopWhichDoesNotLoopInspection */ + foreach ($kids->value as $reference) { + $reference = PdfIndirectObjectReference::ensure($reference); + $object = $this->parser->getIndirectObject($reference->value); + $type = PdfDictionary::get($object->value, 'Type'); + + if ($type->value === 'Pages') { + return $readPages(PdfDictionary::get($object->value, 'Kids')); + } + + return $object; + } + + throw new PdfReaderException( + 'Kids array cannot be empty.', + PdfReaderException::KIDS_EMPTY + ); + }; + + $page = $this->parser->getIndirectObject($page->value); + $dict = PdfType::resolve($page, $this->parser); + $type = PdfDictionary::get($dict, 'Type'); + + if ($type->value === 'Pages') { + $kids = PdfType::resolve(PdfDictionary::get($dict, 'Kids'), $this->parser); + try { + $page = $this->pages[$pageNumber - 1] = $readPages($kids); + } catch (PdfReaderException $e) { + if ($e->getCode() !== PdfReaderException::KIDS_EMPTY) { + throw $e; + } + + // let's reset the pages array and read all page objects + $this->pages = []; + $this->readPages(true); + // @phpstan-ignore-next-line + $page = $this->pages[$pageNumber - 1]; + } + } else { + $this->pages[$pageNumber - 1] = $page; + } + } + + return new Page($page, $this->parser); + } + + /** + * Walk the page tree and resolve all indirect objects of all pages. + * + * @param bool $readAll + * @throws CrossReferenceException + * @throws PdfParserException + * @throws PdfTypeException + */ + protected function readPages($readAll = false) + { + if (\count($this->pages) > 0) { + return; + } + + $expectedPageCount = $this->getPageCount(); + $readPages = function ($kids, $count) use (&$readPages, $readAll, $expectedPageCount) { + $kids = PdfArray::ensure($kids); + $isLeaf = ($count->value === \count($kids->value)); + + foreach ($kids->value as $reference) { + $reference = PdfIndirectObjectReference::ensure($reference); + + if (!$readAll && $isLeaf) { + $this->pages[] = $reference; + continue; + } + + $object = $this->parser->getIndirectObject($reference->value); + $type = PdfDictionary::get($object->value, 'Type'); + + if ($type->value === 'Pages') { + $readPages(PdfDictionary::get($object->value, 'Kids'), PdfDictionary::get($object->value, 'Count')); + } else { + $this->pages[] = $object; + } + + // stop if all pages are read - faulty documents exists with additional entries with invalid data. + if (count($this->pages) === $expectedPageCount) { + break; + } + } + }; + + $catalog = $this->parser->getCatalog(); + $pages = PdfType::resolve(PdfDictionary::get($catalog, 'Pages'), $this->parser); + $count = PdfType::resolve(PdfDictionary::get($pages, 'Count'), $this->parser); + $kids = PdfType::resolve(PdfDictionary::get($pages, 'Kids'), $this->parser); + $readPages($kids, $count); + } +} diff --git a/src/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php b/src/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php new file mode 100644 index 000000000..ecebdb961 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/PdfReader/PdfReaderException.php @@ -0,0 +1,34 @@ +cleanUp(); + } + + /** + * Get the next template id. + * + * @return int + */ + protected function getNextTemplateId() + { + return $this->templateId++; + } + + /** + * Draws an imported page onto the page or another template. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see FpdiTrait::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + return $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); + } + + /** + * Draws an imported page onto the page. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $pageId The page id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size. + * @see Fpdi::getTemplateSize() + */ + public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + $size = $this->fpdiUseImportedPage($pageId, $x, $y, $width, $height, $adjustPageSize); + if ($this->inxobj) { + $importedPage = $this->importedPages[$pageId]; + $this->xobjects[$this->xobjid]['importedPages'][$importedPage['id']] = $pageId; + } + + return $size; + } + + /** + * Get the size of an imported page. + * + * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the + * aspect ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + return $this->getImportedPageSize($tpl, $width, $height); + } + + /** + * @inheritdoc + * @return string + */ + protected function _getxobjectdict() + { + $out = parent::_getxobjectdict(); + + foreach ($this->importedPages as $pageData) { + $out .= '/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R '; + } + + return $out; + } + + /** + * @inheritdoc + * @throws CrossReferenceException + * @throws PdfParserException + */ + protected function _putxobjects() + { + foreach ($this->importedPages as $key => $pageData) { + $this->currentObjectNumber = $this->_newobj(); + $this->importedPages[$key]['objectNumber'] = $this->currentObjectNumber; + $this->currentReaderId = $pageData['readerId']; + $this->writePdfType($pageData['stream']); + $this->_put('endobj'); + } + + foreach (\array_keys($this->readers) as $readerId) { + $parser = $this->getPdfReader($readerId)->getParser(); + $this->currentReaderId = $readerId; + + while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { + try { + $object = $parser->getIndirectObject($objectNumber); + } catch (CrossReferenceException $e) { + if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { + $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); + } else { + throw $e; + } + } + + $this->writePdfType($object); + } + } + + // let's prepare resources for imported pages in templates + foreach ($this->xobjects as $xObjectId => $data) { + if (!isset($data['importedPages'])) { + continue; + } + + foreach ($data['importedPages'] as $id => $pageKey) { + $page = $this->importedPages[$pageKey]; + $this->xobjects[$xObjectId]['xobjects'][$id] = ['n' => $page['objectNumber']]; + } + } + + + parent::_putxobjects(); + $this->currentObjectNumber = null; + } + + /** + * Append content to the buffer of TCPDF. + * + * @param string $s + * @param bool $newLine + */ + protected function _put($s, $newLine = true) + { + if ($newLine) { + $this->setBuffer($s . "\n"); + } else { + $this->setBuffer($s); + } + } + + /** + * Begin a new object and return the object number. + * + * @param int|string $objid Object ID (leave empty to get a new ID). + * @return int object number + */ + protected function _newobj($objid = '') + { + $this->_out($this->_getobj($objid)); + return $this->n; + } + + /** + * Writes a PdfType object to the resulting buffer. + * + * @param PdfType $value + * @throws PdfTypeException + */ + protected function writePdfType(PdfType $value) + { + if (!$this->encrypted) { + $this->fpdiWritePdfType($value); + return; + } + + if ($value instanceof PdfString) { + $string = PdfString::unescape($value->value); + $string = $this->_encrypt_data($this->currentObjectNumber, $string); + $value->value = PdfString::escape($string); + } elseif ($value instanceof PdfHexString) { + $filter = new AsciiHex(); + $string = $filter->decode($value->value); + $string = $this->_encrypt_data($this->currentObjectNumber, $string); + $value->value = $filter->encode($string, true); + } elseif ($value instanceof PdfStream) { + $stream = $value->getStream(); + $stream = $this->_encrypt_data($this->currentObjectNumber, $stream); + $dictionary = $value->value; + $dictionary->value['Length'] = PdfNumeric::create(\strlen($stream)); + $value = PdfStream::create($dictionary, $stream); + } elseif ($value instanceof PdfIndirectObject) { + /** + * @var PdfIndirectObject $value + */ + $this->currentObjectNumber = $this->objectMap[$this->currentReaderId][$value->objectNumber]; + } + + $this->fpdiWritePdfType($value); + } + + /** + * This method will add additional data to the last created link/annotation. + * + * It will copy styling properties (supported by TCPDF) of the imported link. + * + * @param array $externalLink + * @param float|int $xPt + * @param float|int $scaleX + * @param float|int $yPt + * @param float|int $newHeightPt + * @param float|int $scaleY + * @param array $importedPage + * @return void + */ + protected function adjustLastLink($externalLink, $xPt, $scaleX, $yPt, $newHeightPt, $scaleY, $importedPage) + { + $parser = $this->getPdfReader($importedPage['readerId'])->getParser(); + + if ($this->inxobj) { + // store parameters for later use on template + $lastAnnotationKey = count($this->xobjects[$this->xobjid]['annotations']) - 1; + $lastAnnotationOpt = &$this->xobjects[$this->xobjid]['annotations'][$lastAnnotationKey]['opt']; + } else { + $lastAnnotationKey = count($this->PageAnnots[$this->page]) - 1; + $lastAnnotationOpt = &$this->PageAnnots[$this->page][$lastAnnotationKey]['opt']; + } + + // ensure we have a default value - otherwise TCPDF will set it to 4 throughout + $lastAnnotationOpt['f'] = 0; + + // values in this dictonary are all direct objects and we don't need to resolve them here again. + $values = $externalLink['pdfObject']->value; + + foreach ($values as $key => $value) { + try { + switch ($key) { + case 'BS': + $value = PdfDictionary::ensure($value); + $bs = []; + if (isset($value->value['W'])) { + $bs['w'] = PdfNumeric::ensure($value->value['W'])->value; + } + + if (isset($value->value['S'])) { + $bs['s'] = PdfName::ensure($value->value['S'])->value; + } + + if (isset($value->value['D'])) { + $d = []; + foreach (PdfArray::ensure($value->value['D'])->value as $item) { + $d[] = PdfNumeric::ensure($item)->value; + } + $bs['d'] = $d; + } + + $lastAnnotationOpt['bs'] = $bs; + break; + + case 'Border': + $borderArray = PdfArray::ensure($value)->value; + if (count($borderArray) < 3) { + continue 2; + } + + $border = [ + PdfNumeric::ensure($borderArray[0])->value, + PdfNumeric::ensure($borderArray[1])->value, + PdfNumeric::ensure($borderArray[2])->value, + ]; + if (isset($borderArray[3])) { + $dashArray = []; + foreach (PdfArray::ensure($borderArray[3])->value as $item) { + $dashArray[] = PdfNumeric::ensure($item)->value; + } + $border[] = $dashArray; + } + + $lastAnnotationOpt['border'] = $border; + break; + + case 'C': + $c = []; + $colors = PdfArray::ensure(PdfType::resolve($value, $parser))->value; + $m = count($colors) === 4 ? 100 : 255; + foreach ($colors as $item) { + $c[] = PdfNumeric::ensure($item)->value * $m; + } + $lastAnnotationOpt['c'] = $c; + break; + + case 'F': + $lastAnnotationOpt['f'] = $value->value; + break; + + case 'BE': + // is broken in current TCPDF version: "bc" key is checked but "bs" is used. + break; + } + // let's silence invalid/not supported values + } catch (FpdiException $e) { + continue; + } + } + + // QuadPoints are not supported by TCPDF +// if (count($externalLink['quadPoints']) > 0) { +// $quadPoints = []; +// for ($i = 0, $n = count($externalLink['quadPoints']); $i < $n; $i += 2) { +// $quadPoints[] = $xPt + $externalLink['quadPoints'][$i] * $scaleX; +// $quadPoints[] = $this->hPt - $yPt - $newHeightPt + $externalLink['quadPoints'][$i + 1] * $scaleY; +// } +// +// ????? = $quadPoints; +// } + } +} diff --git a/src/vendor/setasign/fpdi/src/TcpdfFpdi.php b/src/vendor/setasign/fpdi/src/TcpdfFpdi.php new file mode 100644 index 000000000..84f681969 --- /dev/null +++ b/src/vendor/setasign/fpdi/src/TcpdfFpdi.php @@ -0,0 +1,23 @@ +doGet($this, $key, $callback, $beta, $metadata); } @@ -43,7 +43,7 @@ trait CacheTrait return $this->deleteItem($key); } - private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null, ?LoggerInterface $logger = null) + private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null) { if (0 > $beta = $beta ?? 1.0) { throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { }; diff --git a/src/vendor/symfony/cache-contracts/LICENSE b/src/vendor/symfony/cache-contracts/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/src/vendor/symfony/cache-contracts/LICENSE +++ b/src/vendor/symfony/cache-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/cache/Adapter/AbstractAdapter.php b/src/vendor/symfony/cache/Adapter/AbstractAdapter.php index de5af1793..0d1c671fe 100644 --- a/src/vendor/symfony/cache/Adapter/AbstractAdapter.php +++ b/src/vendor/symfony/cache/Adapter/AbstractAdapter.php @@ -101,7 +101,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg * * @return AdapterInterface */ - public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, ?LoggerInterface $logger = null) + public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null) { $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); if (null !== $logger) { @@ -112,7 +112,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg return $opcache; } - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { return $opcache; } @@ -140,7 +140,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg return CouchbaseCollectionAdapter::createConnection($dsn, $options); } - throw new InvalidArgumentException('Unsupported DSN: it does not start with "redis[s]:", "memcached:" nor "couchbase:".'); + throw new InvalidArgumentException(sprintf('Unsupported DSN: "%s".', $dsn)); } /** diff --git a/src/vendor/symfony/cache/Adapter/ApcuAdapter.php b/src/vendor/symfony/cache/Adapter/ApcuAdapter.php index 639e31441..5fc8f6295 100644 --- a/src/vendor/symfony/cache/Adapter/ApcuAdapter.php +++ b/src/vendor/symfony/cache/Adapter/ApcuAdapter.php @@ -25,7 +25,7 @@ class ApcuAdapter extends AbstractAdapter /** * @throws CacheException if APCu is not enabled */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $version = null, ?MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('APCu is not enabled.'); @@ -49,7 +49,7 @@ class ApcuAdapter extends AbstractAdapter public static function isSupported() { - return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); + return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); } /** @@ -94,8 +94,8 @@ class ApcuAdapter extends AbstractAdapter */ protected function doClear(string $namespace) { - return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) - ? apcu_delete(new \APCUIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) + return isset($namespace[0]) && class_exists(\APCuIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) + ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) : apcu_clear_cache(); } diff --git a/src/vendor/symfony/cache/Adapter/ArrayAdapter.php b/src/vendor/symfony/cache/Adapter/ArrayAdapter.php index b251814eb..bd5ec9ec9 100644 --- a/src/vendor/symfony/cache/Adapter/ArrayAdapter.php +++ b/src/vendor/symfony/cache/Adapter/ArrayAdapter.php @@ -73,7 +73,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { $item = $this->getItem($key); $metadata = $item->getMetadata(); @@ -81,10 +81,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter // ArrayAdapter works in memory, we don't care about stampede protection if (\INF === $beta || !$item->isHit()) { $save = true; - $item->set($callback($item, $save)); - if ($save) { - $this->save($item); - } + $this->save($item->set($callback($item, $save))); } return $item->get(); @@ -349,7 +346,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { return serialize($value); } - } elseif (!\is_scalar($value)) { + } elseif (!is_scalar($value)) { try { $serialized = serialize($value); } catch (\Exception $e) { diff --git a/src/vendor/symfony/cache/Adapter/ChainAdapter.php b/src/vendor/symfony/cache/Adapter/ChainAdapter.php index 7d9552836..568069763 100644 --- a/src/vendor/symfony/cache/Adapter/ChainAdapter.php +++ b/src/vendor/symfony/cache/Adapter/ChainAdapter.php @@ -53,7 +53,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa if (!$adapter instanceof CacheItemPoolInterface) { throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($adapter), CacheItemPoolInterface::class)); } - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { continue; // skip putting APCu in the chain when the backend is disabled } @@ -92,19 +92,11 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { - $doSave = true; - $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) { - $value = $callback($item, $save); - $doSave = $save; - - return $value; - }; - $lastItem = null; $i = 0; - $wrap = function (?CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$i, &$doSave, &$lastItem, &$metadata) { + $wrap = function (CacheItem $item = null) use ($key, $callback, $beta, &$wrap, &$i, &$lastItem, &$metadata) { $adapter = $this->adapters[$i]; if (isset($this->adapters[++$i])) { $callback = $wrap; @@ -118,7 +110,6 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa if (null !== $item) { (self::$syncItem)($lastItem = $lastItem ?? $item, $item, $this->defaultLifetime, $metadata); } - $save = $doSave; return $value; }; diff --git a/src/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php b/src/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php index 84ab28143..36d5249b4 100644 --- a/src/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php +++ b/src/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php @@ -39,7 +39,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter private $bucket; private $marshaller; - public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); @@ -83,7 +83,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter foreach ($servers as $dsn) { if (0 !== strpos($dsn, 'couchbase:')) { - throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".'); + throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $dsn)); } preg_match($dsnPattern, $dsn, $matches); diff --git a/src/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/src/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php index c0a1317d2..79f648531 100644 --- a/src/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php +++ b/src/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php @@ -33,7 +33,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter private $connection; private $marshaller; - public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.'); @@ -79,7 +79,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter foreach ($dsn as $server) { if (0 !== strpos($server, 'couchbase:')) { - throw new InvalidArgumentException('Invalid Couchbase DSN: it does not start with "couchbase:".'); + throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $server)); } preg_match($dsnPattern, $server, $matches); diff --git a/src/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php b/src/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php index c12682413..73f0ea6bc 100644 --- a/src/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php +++ b/src/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php @@ -11,18 +11,13 @@ namespace Symfony\Component\Cache\Adapter; -use Doctrine\DBAL\ArrayParameterType; -use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\ParameterType; -use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; use Doctrine\DBAL\Schema\Schema; -use Doctrine\DBAL\ServerVersionProvider; -use Doctrine\DBAL\Tools\DsnParser; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Marshaller\DefaultMarshaller; use Symfony\Component\Cache\Marshaller\MarshallerInterface; @@ -61,7 +56,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface * * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null) + public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) { if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); @@ -71,30 +66,9 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface $this->conn = $connOrDsn; } elseif (\is_string($connOrDsn)) { if (!class_exists(DriverManager::class)) { - throw new InvalidArgumentException('Failed to parse DSN. Try running "composer require doctrine/dbal".'); + throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $connOrDsn)); } - if (class_exists(DsnParser::class)) { - $params = (new DsnParser([ - 'db2' => 'ibm_db2', - 'mssql' => 'pdo_sqlsrv', - 'mysql' => 'pdo_mysql', - 'mysql2' => 'pdo_mysql', - 'postgres' => 'pdo_pgsql', - 'postgresql' => 'pdo_pgsql', - 'pgsql' => 'pdo_pgsql', - 'sqlite' => 'pdo_sqlite', - 'sqlite3' => 'pdo_sqlite', - ]))->parse($connOrDsn); - } else { - $params = ['url' => $connOrDsn]; - } - - $config = new Configuration(); - if (class_exists(DefaultSchemaManagerFactory::class)) { - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - } - - $this->conn = DriverManager::getConnection($params, $config); + $this->conn = DriverManager::getConnection(['url' => $connOrDsn]); } else { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be "%s" or string, "%s" given.', __METHOD__, Connection::class, get_debug_type($connOrDsn))); } @@ -182,7 +156,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface $ids, ], [ ParameterType::INTEGER, - class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY, + Connection::PARAM_STR_ARRAY, ])->iterateNumeric(); foreach ($result as $row) { @@ -200,7 +174,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface $expired, ], [ ParameterType::INTEGER, - class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY, + Connection::PARAM_STR_ARRAY, ]); } } @@ -252,7 +226,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface { $sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)"; try { - $this->conn->executeStatement($sql, [array_values($ids)], [class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING : Connection::PARAM_STR_ARRAY]); + $this->conn->executeStatement($sql, [array_values($ids)], [Connection::PARAM_STR_ARRAY]); } catch (TableNotFoundException $e) { } @@ -311,42 +285,35 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface $stmt = $this->conn->prepare($sql); } + // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution. if ('sqlsrv' === $platformName || 'oci' === $platformName) { - $bind = static function ($id, $data) use ($stmt) { - $stmt->bindValue(1, $id); - $stmt->bindValue(2, $id); - $stmt->bindValue(3, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(6, $data, ParameterType::LARGE_OBJECT); - }; + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $id); + $stmt->bindParam(3, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(4, $lifetime, ParameterType::INTEGER); $stmt->bindValue(5, $now, ParameterType::INTEGER); + $stmt->bindParam(6, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(7, $lifetime, ParameterType::INTEGER); $stmt->bindValue(8, $now, ParameterType::INTEGER); } elseif (null !== $platformName) { - $bind = static function ($id, $data) use ($stmt) { - $stmt->bindValue(1, $id); - $stmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); - }; + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(3, $lifetime, ParameterType::INTEGER); $stmt->bindValue(4, $now, ParameterType::INTEGER); } else { + $stmt->bindParam(1, $data, ParameterType::LARGE_OBJECT); $stmt->bindValue(2, $lifetime, ParameterType::INTEGER); $stmt->bindValue(3, $now, ParameterType::INTEGER); + $stmt->bindParam(4, $id); $insertStmt = $this->conn->prepare($insertSql); + $insertStmt->bindParam(1, $id); + $insertStmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER); $insertStmt->bindValue(4, $now, ParameterType::INTEGER); - - $bind = static function ($id, $data) use ($stmt, $insertStmt) { - $stmt->bindValue(1, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(4, $id); - $insertStmt->bindValue(1, $id); - $insertStmt->bindValue(2, $data, ParameterType::LARGE_OBJECT); - }; } foreach ($values as $id => $data) { - $bind($id, $data); try { $rowCount = $stmt->executeStatement(); } catch (TableNotFoundException $e) { @@ -367,22 +334,6 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface return $failed; } - /** - * @internal - */ - protected function getId($key) - { - if ('pgsql' !== $this->getPlatformName()) { - return parent::getId($key); - } - - if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { - $key = rawurlencode($key); - } - - return parent::getId($key); - } - private function getPlatformName(): string { if (isset($this->platformName)) { @@ -421,14 +372,12 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface return $this->serverVersion; } - if ($this->conn instanceof ServerVersionProvider || $this->conn instanceof ServerInfoAwareConnection) { - return $this->serverVersion = $this->conn->getServerVersion(); + $conn = $this->conn->getWrappedConnection(); + if ($conn instanceof ServerInfoAwareConnection) { + return $this->serverVersion = $conn->getServerVersion(); } - // The condition should be removed once support for DBAL <3.3 is dropped - $conn = method_exists($this->conn, 'getNativeConnection') ? $this->conn->getNativeConnection() : $this->conn->getWrappedConnection(); - - return $this->serverVersion = $conn->getAttribute(\PDO::ATTR_SERVER_VERSION); + return $this->serverVersion = '0'; } private function addTableToSchema(Schema $schema): void diff --git a/src/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/src/vendor/symfony/cache/Adapter/FilesystemAdapter.php index 13daa568c..7185dd487 100644 --- a/src/vendor/symfony/cache/Adapter/FilesystemAdapter.php +++ b/src/vendor/symfony/cache/Adapter/FilesystemAdapter.php @@ -20,7 +20,7 @@ class FilesystemAdapter extends AbstractAdapter implements PruneableInterface { use FilesystemTrait; - public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) { $this->marshaller = $marshaller ?? new DefaultMarshaller(); parent::__construct('', $defaultLifetime); diff --git a/src/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/src/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php index 440a37af5..afde84375 100644 --- a/src/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php +++ b/src/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php @@ -34,7 +34,7 @@ class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements Prune */ private const TAG_FOLDER = 'tags'; - public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) { $this->marshaller = new TagAwareMarshaller($marshaller); parent::__construct('', $defaultLifetime); diff --git a/src/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/src/vendor/symfony/cache/Adapter/MemcachedAdapter.php index 0bc20d4b7..5c2933fcf 100644 --- a/src/vendor/symfony/cache/Adapter/MemcachedAdapter.php +++ b/src/vendor/symfony/cache/Adapter/MemcachedAdapter.php @@ -32,6 +32,13 @@ class MemcachedAdapter extends AbstractAdapter protected $maxIdLength = 250; + private const DEFAULT_CLIENT_OPTIONS = [ + 'persistent_id' => null, + 'username' => null, + 'password' => null, + \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, + ]; + private $marshaller; private $client; private $lazyClient; @@ -46,7 +53,7 @@ class MemcachedAdapter extends AbstractAdapter * * Using a MemcachedAdapter as a pure items store is fine. */ - public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.'); @@ -99,9 +106,10 @@ class MemcachedAdapter extends AbstractAdapter } set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); try { - $client = new \Memcached($options['persistent_id'] ?? null); - $username = $options['username'] ?? null; - $password = $options['password'] ?? null; + $options += static::DEFAULT_CLIENT_OPTIONS; + $client = new \Memcached($options['persistent_id']); + $username = $options['username']; + $password = $options['password']; // parse any DSN in $servers foreach ($servers as $i => $dsn) { @@ -109,19 +117,17 @@ class MemcachedAdapter extends AbstractAdapter continue; } if (!str_starts_with($dsn, 'memcached:')) { - throw new InvalidArgumentException('Invalid Memcached DSN: it does not start with "memcached:".'); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached:".', $dsn)); } $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[2])) { [$username, $password] = explode(':', $m[2], 2) + [1 => null]; - $username = rawurldecode($username); - $password = null !== $password ? rawurldecode($password) : null; } return 'file:'.($m[1] ?? ''); }, $dsn); if (false === $params = parse_url($params)) { - throw new InvalidArgumentException('Invalid Memcached DSN.'); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } $query = $hosts = []; if (isset($params['query'])) { @@ -129,7 +135,7 @@ class MemcachedAdapter extends AbstractAdapter if (isset($query['host'])) { if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException('Invalid Memcached DSN: query parameter "host" must be an array.'); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } foreach ($hosts as $host => $weight) { if (false === $port = strrpos($host, ':')) { @@ -148,7 +154,7 @@ class MemcachedAdapter extends AbstractAdapter } } if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException('Invalid Memcached DSN: missing host or path.'); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { $params['weight'] = $m[1]; @@ -193,7 +199,7 @@ class MemcachedAdapter extends AbstractAdapter $options[\constant('Memcached::OPT_'.$name)] = $value; } } - $client->setOptions($options + [\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP]); + $client->setOptions($options); // set client's servers, taking care of persistent connections if (!$client->isPristine()) { diff --git a/src/vendor/symfony/cache/Adapter/NullAdapter.php b/src/vendor/symfony/cache/Adapter/NullAdapter.php index bf5382ffd..15f7f8c45 100644 --- a/src/vendor/symfony/cache/Adapter/NullAdapter.php +++ b/src/vendor/symfony/cache/Adapter/NullAdapter.php @@ -40,7 +40,7 @@ class NullAdapter implements AdapterInterface, CacheInterface /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { $save = true; diff --git a/src/vendor/symfony/cache/Adapter/PdoAdapter.php b/src/vendor/symfony/cache/Adapter/PdoAdapter.php index a2a275b86..5d1072443 100644 --- a/src/vendor/symfony/cache/Adapter/PdoAdapter.php +++ b/src/vendor/symfony/cache/Adapter/PdoAdapter.php @@ -34,8 +34,8 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface private $dataCol = 'item_data'; private $lifetimeCol = 'item_lifetime'; private $timeCol = 'item_time'; - private $username = null; - private $password = null; + private $username = ''; + private $password = ''; private $connectionOptions = []; private $namespace; @@ -62,7 +62,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null) + public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) { if ($connOrDsn instanceof Connection || (\is_string($connOrDsn) && str_contains($connOrDsn, '://'))) { trigger_deprecation('symfony/cache', '5.4', 'Usage of a DBAL Connection with "%s" is deprecated and will be removed in symfony 6.0. Use "%s" instead.', __CLASS__, DoctrineDbalAdapter::class); @@ -176,7 +176,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface /** * {@inheritDoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { if (isset($this->dbalAdapter)) { return $this->dbalAdapter->get($key, $callback, $beta, $metadata); @@ -507,7 +507,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface try { $stmt = $conn->prepare($sql); } catch (\PDOException $e) { - if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { $this->createTable(); } $stmt = $conn->prepare($sql); @@ -542,7 +542,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface try { $stmt->execute(); } catch (\PDOException $e) { - if ($this->isTableMissing($e) && (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true))) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { $this->createTable(); } $stmt->execute(); @@ -559,22 +559,6 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface return $failed; } - /** - * @internal - */ - protected function getId($key) - { - if ('pgsql' !== $this->driver ?? ($this->getConnection() ? $this->driver : null)) { - return parent::getId($key); - } - - if (str_contains($key, "\0") || str_contains($key, '%') || !preg_match('//u', $key)) { - $key = rawurlencode($key); - } - - return parent::getId($key); - } - private function getConnection(): \PDO { if (null === $this->conn) { @@ -596,21 +580,4 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface return $this->serverVersion; } - - private function isTableMissing(\PDOException $exception): bool - { - $driver = $this->driver; - [$sqlState, $code] = $exception->errorInfo ?? [null, $exception->getCode()]; - - switch (true) { - case 'pgsql' === $driver && '42P01' === $sqlState: - case 'sqlite' === $driver && str_contains($exception->getMessage(), 'no such table:'): - case 'oci' === $driver && 942 === $code: - case 'sqlsrv' === $driver && 208 === $code: - case 'mysql' === $driver && 1146 === $code: - return true; - default: - return false; - } - } } diff --git a/src/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/src/vendor/symfony/cache/Adapter/PhpArrayAdapter.php index 43e000a99..7e9b6b3f3 100644 --- a/src/vendor/symfony/cache/Adapter/PhpArrayAdapter.php +++ b/src/vendor/symfony/cache/Adapter/PhpArrayAdapter.php @@ -83,7 +83,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { if (null === $this->values) { $this->initialize(); @@ -345,7 +345,7 @@ EOF; $isStaticValue = false; } $value = var_export($value, true); - } elseif (!\is_scalar($value)) { + } elseif (!is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); } else { $value = var_export($value, true); diff --git a/src/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/src/vendor/symfony/cache/Adapter/PhpFilesAdapter.php index 8dcd79cd9..f5766c330 100644 --- a/src/vendor/symfony/cache/Adapter/PhpFilesAdapter.php +++ b/src/vendor/symfony/cache/Adapter/PhpFilesAdapter.php @@ -43,7 +43,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface * * @throws CacheException if OPcache is not enabled */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, bool $appendOnly = false) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) { $this->appendOnly = $appendOnly; self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); @@ -58,7 +58,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface { self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); - return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)); + return \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)); } /** @@ -82,7 +82,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface } if ($time >= $expiresAt) { - $pruned = ($this->doUnlink($file) || !file_exists($file)) && $pruned; + $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned; } } } finally { @@ -234,7 +234,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface $isStaticValue = false; } $value = var_export($value, true); - } elseif (!\is_scalar($value)) { + } elseif (!is_scalar($value)) { throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); } else { $value = var_export($value, true); diff --git a/src/vendor/symfony/cache/Adapter/ProxyAdapter.php b/src/vendor/symfony/cache/Adapter/ProxyAdapter.php index 317018e59..c715cade5 100644 --- a/src/vendor/symfony/cache/Adapter/ProxyAdapter.php +++ b/src/vendor/symfony/cache/Adapter/ProxyAdapter.php @@ -102,7 +102,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { if (!$this->pool instanceof CacheInterface) { return $this->doGet($this, $key, $callback, $beta, $metadata); diff --git a/src/vendor/symfony/cache/Adapter/RedisAdapter.php b/src/vendor/symfony/cache/Adapter/RedisAdapter.php index 86714ae43..eb5950e53 100644 --- a/src/vendor/symfony/cache/Adapter/RedisAdapter.php +++ b/src/vendor/symfony/cache/Adapter/RedisAdapter.php @@ -25,7 +25,7 @@ class RedisAdapter extends AbstractAdapter * @param string $namespace The default namespace * @param int $defaultLifetime The default lifetime */ - public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { $this->init($redis, $namespace, $defaultLifetime, $marshaller); } diff --git a/src/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/src/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php index 958486e0f..865491e19 100644 --- a/src/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php +++ b/src/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php @@ -66,7 +66,7 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter * @param string $namespace The default namespace * @param int $defaultLifetime The default lifetime */ - public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) + public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) { if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) { throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection()))); @@ -208,7 +208,7 @@ EOLUA; // and removes the linked items. When the set is still not empty after // the scan, it means we're in cluster mode and that the linked items // are on other nodes: we move the links to a temporary set and we - // garbage collect that set from the client side. + // gargage collect that set from the client side. $lua = <<<'EOLUA' redis.replicate_commands() diff --git a/src/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/src/vendor/symfony/cache/Adapter/TagAwareAdapter.php index fb59599eb..ff22e5a8a 100644 --- a/src/vendor/symfony/cache/Adapter/TagAwareAdapter.php +++ b/src/vendor/symfony/cache/Adapter/TagAwareAdapter.php @@ -43,7 +43,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac private static $getTagsByKey; private static $saveTags; - public function __construct(AdapterInterface $itemsPool, ?AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) { $this->pool = $itemsPool; $this->tags = $tagsPool ?: $itemsPool; diff --git a/src/vendor/symfony/cache/Adapter/TraceableAdapter.php b/src/vendor/symfony/cache/Adapter/TraceableAdapter.php index 06951db26..4b06557f8 100644 --- a/src/vendor/symfony/cache/Adapter/TraceableAdapter.php +++ b/src/vendor/symfony/cache/Adapter/TraceableAdapter.php @@ -38,7 +38,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt /** * {@inheritdoc} */ - public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null) + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) { if (!$this->pool instanceof CacheInterface) { throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class)); diff --git a/src/vendor/symfony/cache/CacheItem.php b/src/vendor/symfony/cache/CacheItem.php index 091d9e9b8..cf39b4cc8 100644 --- a/src/vendor/symfony/cache/CacheItem.php +++ b/src/vendor/symfony/cache/CacheItem.php @@ -182,7 +182,7 @@ final class CacheItem implements ItemInterface } else { $replace = []; foreach ($context as $k => $v) { - if (\is_scalar($v)) { + if (is_scalar($v)) { $replace['{'.$k.'}'] = $v; } } diff --git a/src/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/src/vendor/symfony/cache/DataCollector/CacheDataCollector.php index 047958099..9590436dc 100644 --- a/src/vendor/symfony/cache/DataCollector/CacheDataCollector.php +++ b/src/vendor/symfony/cache/DataCollector/CacheDataCollector.php @@ -39,7 +39,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter /** * {@inheritdoc} */ - public function collect(Request $request, Response $response, ?\Throwable $exception = null) + public function collect(Request $request, Response $response, \Throwable $exception = null) { $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; $this->data = ['instances' => $empty, 'total' => $empty]; @@ -114,7 +114,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter /** @var TraceableAdapterEvent $call */ foreach ($calls as $call) { ++$statistics[$name]['calls']; - $statistics[$name]['time'] += ($call->end ?? microtime(true)) - $call->start; + $statistics[$name]['time'] += $call->end - $call->start; if ('get' === $call->name) { ++$statistics[$name]['reads']; if ($call->hits) { @@ -136,8 +136,10 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter $statistics[$name]['misses'] += $call->misses; } elseif ('hasItem' === $call->name) { ++$statistics[$name]['reads']; - foreach ($call->result ?? [] as $result) { - ++$statistics[$name][$result ? 'hits' : 'misses']; + if (false === $call->result) { + ++$statistics[$name]['misses']; + } else { + ++$statistics[$name]['hits']; } } elseif ('save' === $call->name) { ++$statistics[$name]['writes']; diff --git a/src/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/src/vendor/symfony/cache/DependencyInjection/CachePoolPass.php index ee539af77..14ac2bde4 100644 --- a/src/vendor/symfony/cache/DependencyInjection/CachePoolPass.php +++ b/src/vendor/symfony/cache/DependencyInjection/CachePoolPass.php @@ -209,10 +209,10 @@ class CachePoolPass implements CompilerPassInterface } $notAliasedCacheClearerId = $this->cacheClearerId; - while ($container->hasAlias($notAliasedCacheClearerId)) { - $notAliasedCacheClearerId = (string) $container->getAlias($notAliasedCacheClearerId); + while ($container->hasAlias($this->cacheClearerId)) { + $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId); } - if ($container->hasDefinition($notAliasedCacheClearerId)) { + if ($container->hasDefinition($this->cacheClearerId)) { $clearers[$notAliasedCacheClearerId] = $allPools; } diff --git a/src/vendor/symfony/cache/LICENSE b/src/vendor/symfony/cache/LICENSE index 0223acd4a..7fa953905 100644 --- a/src/vendor/symfony/cache/LICENSE +++ b/src/vendor/symfony/cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-present Fabien Potencier +Copyright (c) 2016-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/cache/LockRegistry.php b/src/vendor/symfony/cache/LockRegistry.php index d0c5fc5ba..65f20bb73 100644 --- a/src/vendor/symfony/cache/LockRegistry.php +++ b/src/vendor/symfony/cache/LockRegistry.php @@ -84,7 +84,7 @@ final class LockRegistry return $previousFiles; } - public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, ?\Closure $setMetadata = null, ?LoggerInterface $logger = null) + public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null) { if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) { // disable locking on Windows by default diff --git a/src/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/src/vendor/symfony/cache/Marshaller/DefaultMarshaller.php index 43f7e7e2a..3202dd69c 100644 --- a/src/vendor/symfony/cache/Marshaller/DefaultMarshaller.php +++ b/src/vendor/symfony/cache/Marshaller/DefaultMarshaller.php @@ -23,7 +23,7 @@ class DefaultMarshaller implements MarshallerInterface private $useIgbinarySerialize = true; private $throwOnSerializationFailure; - public function __construct(?bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) + public function __construct(bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) { if (null === $useIgbinarySerialize) { $useIgbinarySerialize = \extension_loaded('igbinary') && (\PHP_VERSION_ID < 70400 || version_compare('3.1.6', phpversion('igbinary'), '<=')); diff --git a/src/vendor/symfony/cache/Marshaller/SodiumMarshaller.php b/src/vendor/symfony/cache/Marshaller/SodiumMarshaller.php index 7895ef557..dbf486a72 100644 --- a/src/vendor/symfony/cache/Marshaller/SodiumMarshaller.php +++ b/src/vendor/symfony/cache/Marshaller/SodiumMarshaller.php @@ -29,7 +29,7 @@ class SodiumMarshaller implements MarshallerInterface * more rotating keys can be provided to decrypt values; * each key must be generated using sodium_crypto_box_keypair() */ - public function __construct(array $decryptionKeys, ?MarshallerInterface $marshaller = null) + public function __construct(array $decryptionKeys, MarshallerInterface $marshaller = null) { if (!self::isSupported()) { throw new CacheException('The "sodium" PHP extension is not loaded.'); diff --git a/src/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/src/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php index f2f26abcf..5d1e303b4 100644 --- a/src/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php +++ b/src/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php @@ -20,7 +20,7 @@ class TagAwareMarshaller implements MarshallerInterface { private $marshaller; - public function __construct(?MarshallerInterface $marshaller = null) + public function __construct(MarshallerInterface $marshaller = null) { $this->marshaller = $marshaller ?? new DefaultMarshaller(); } @@ -51,7 +51,7 @@ class TagAwareMarshaller implements MarshallerInterface $serialized[$id][9] = "\x5F"; } } else { - // other arbitrary values are serialized using the decorated marshaller below + // other arbitratry values are serialized using the decorated marshaller below $notSerialized[$id] = $value; } } diff --git a/src/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php b/src/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php index e09e2826f..6f11b8b5a 100644 --- a/src/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php +++ b/src/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php @@ -27,14 +27,14 @@ class EarlyExpirationDispatcher private $reverseContainer; private $callbackWrapper; - public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, ?callable $callbackWrapper = null) + public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, callable $callbackWrapper = null) { $this->bus = $bus; $this->reverseContainer = $reverseContainer; $this->callbackWrapper = $callbackWrapper; } - public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger = null) + public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, LoggerInterface $logger = null) { if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) { // The item is stale or the callback cannot be reversed: we must compute the value now diff --git a/src/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php b/src/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php index 9e53f5d2f..1f0bd565c 100644 --- a/src/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php +++ b/src/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php @@ -73,8 +73,7 @@ class EarlyExpirationHandler implements MessageHandlerInterface $startTime = microtime(true); $pool = $message->findPool($this->reverseContainer); $callback = $message->findCallback($this->reverseContainer); - $save = true; - $value = $callback($item, $save); + $value = $callback($item); $setMetadata($item, $startTime); $pool->save($item->set($value)); } diff --git a/src/vendor/symfony/cache/README.md b/src/vendor/symfony/cache/README.md index c466d5788..74052052c 100644 --- a/src/vendor/symfony/cache/README.md +++ b/src/vendor/symfony/cache/README.md @@ -1,13 +1,13 @@ Symfony PSR-6 implementation for caching ======================================== -The Cache component provides extended -[PSR-6](https://www.php-fig.org/psr/psr-6/) implementations for adding cache to +The Cache component provides an extended +[PSR-6](http://www.php-fig.org/psr/psr-6/) implementation for adding cache to your applications. It is designed to have a low overhead so that caching is -fastest. It ships with adapters for the most widespread caching backends. -It also provides a [PSR-16](https://www.php-fig.org/psr/psr-16/) adapter, -and implementations for [symfony/cache-contracts](https://github.com/symfony/cache-contracts)' -`CacheInterface` and `TagAwareCacheInterface`. +fastest. It ships with a few caching adapters for the most widespread and +suited to caching backends. It also provides a `doctrine/cache` proxy adapter +to cover more advanced caching needs and a proxy adapter for greater +interoperability between PSR-6 implementations. Resources --------- diff --git a/src/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/src/vendor/symfony/cache/Traits/AbstractAdapterTrait.php index 32d78b185..f0173c422 100644 --- a/src/vendor/symfony/cache/Traits/AbstractAdapterTrait.php +++ b/src/vendor/symfony/cache/Traits/AbstractAdapterTrait.php @@ -297,7 +297,7 @@ trait AbstractAdapterTrait * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, * but old keys may need garbage collection and extra round-trips to the back-end are required. * - * Calling this method also clears the memoized namespace version and thus forces a resynchronization of it. + * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it. * * @return bool the previous state of versioning */ @@ -365,10 +365,7 @@ trait AbstractAdapterTrait } } - /** - * @internal - */ - protected function getId($key) + private function getId($key) { if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { $this->ids = []; @@ -397,7 +394,7 @@ trait AbstractAdapterTrait $this->ids[$key] = $key; if (\count($this->ids) > 1000) { - $this->ids = \array_slice($this->ids, 500, null, true); // stop memory leak if there are many keys + array_splice($this->ids, 0, 500); // stop memory leak if there are many keys } if (null === $this->maxIdLength) { diff --git a/src/vendor/symfony/cache/Traits/ContractsTrait.php b/src/vendor/symfony/cache/Traits/ContractsTrait.php index c22e75fb9..e4d48797f 100644 --- a/src/vendor/symfony/cache/Traits/ContractsTrait.php +++ b/src/vendor/symfony/cache/Traits/ContractsTrait.php @@ -42,7 +42,7 @@ trait ContractsTrait public function setCallbackWrapper(?callable $callbackWrapper): callable { if (!isset($this->callbackWrapper)) { - $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']); + $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']);; if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { $this->setCallbackWrapper(null); @@ -57,7 +57,7 @@ trait ContractsTrait return $previousWrapper; } - private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null) + private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null) { if (0 > $beta = $beta ?? 1.0) { throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)); diff --git a/src/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/src/vendor/symfony/cache/Traits/FilesystemCommonTrait.php index ab7e7dd90..c06cc309a 100644 --- a/src/vendor/symfony/cache/Traits/FilesystemCommonTrait.php +++ b/src/vendor/symfony/cache/Traits/FilesystemCommonTrait.php @@ -88,9 +88,8 @@ trait FilesystemCommonTrait return @unlink($file); } - private function write(string $file, string $data, ?int $expiresAt = null) + private function write(string $file, string $data, int $expiresAt = null) { - $unlink = false; set_error_handler(__CLASS__.'::throwError'); try { if (null === $this->tmp) { @@ -108,31 +107,18 @@ trait FilesystemCommonTrait } fwrite($h, $data); fclose($h); - $unlink = true; if (null !== $expiresAt) { touch($this->tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds } - if ('\\' === \DIRECTORY_SEPARATOR) { - $success = copy($this->tmp, $file); - $unlink = true; - } else { - $success = rename($this->tmp, $file); - $unlink = !$success; - } - - return $success; + return rename($this->tmp, $file); } finally { restore_error_handler(); - - if ($unlink) { - @unlink($this->tmp); - } } } - private function getFile(string $id, bool $mkdir = false, ?string $directory = null) + private function getFile(string $id, bool $mkdir = false, string $directory = null) { // Use MD5 to favor speed over security, which is not an issue here $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true))); diff --git a/src/vendor/symfony/cache/Traits/FilesystemTrait.php b/src/vendor/symfony/cache/Traits/FilesystemTrait.php index f2873d9ef..38b741f1c 100644 --- a/src/vendor/symfony/cache/Traits/FilesystemTrait.php +++ b/src/vendor/symfony/cache/Traits/FilesystemTrait.php @@ -40,7 +40,7 @@ trait FilesystemTrait if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { fclose($h); - $pruned = (@unlink($file) || !file_exists($file)) && $pruned; + $pruned = @unlink($file) && !file_exists($file) && $pruned; } else { fclose($h); } diff --git a/src/vendor/symfony/cache/Traits/RedisTrait.php b/src/vendor/symfony/cache/Traits/RedisTrait.php index 35695d5b1..149c9d4c9 100644 --- a/src/vendor/symfony/cache/Traits/RedisTrait.php +++ b/src/vendor/symfony/cache/Traits/RedisTrait.php @@ -15,8 +15,6 @@ use Predis\Command\Redis\UNLINK; use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\RedisCluster; use Predis\Connection\Aggregate\ReplicationInterface; -use Predis\Connection\Cluster\ClusterInterface as Predis2ClusterInterface; -use Predis\Connection\Cluster\RedisCluster as Predis2RedisCluster; use Predis\Response\ErrorInterface; use Predis\Response\Status; use Symfony\Component\Cache\Exception\CacheException; @@ -98,16 +96,16 @@ trait RedisTrait } elseif (str_starts_with($dsn, 'rediss:')) { $scheme = 'rediss'; } else { - throw new InvalidArgumentException('Invalid Redis DSN: it does not start with "redis[s]:".'); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis:" or "rediss".', $dsn)); } if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { - throw new CacheException('Cannot find the "redis" extension nor the "predis/predis" package.'); + throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: "%s".', $dsn)); } $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { if (isset($m[2])) { - $auth = rawurldecode($m[2]); + $auth = $m[2]; if ('' === $auth) { $auth = null; @@ -118,7 +116,7 @@ trait RedisTrait }, $dsn); if (false === $params = parse_url($params)) { - throw new InvalidArgumentException('Invalid Redis DSN.'); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } $query = $hosts = []; @@ -131,7 +129,7 @@ trait RedisTrait if (isset($query['host'])) { if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException('Invalid Redis DSN: query parameter "host" must be an array.'); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } foreach ($hosts as $host => $parameters) { if (\is_string($parameters)) { @@ -151,11 +149,11 @@ trait RedisTrait if (isset($params['host']) || isset($params['path'])) { if (!isset($params['dbindex']) && isset($params['path'])) { - if (preg_match('#/(\d+)?$#', $params['path'], $m)) { - $params['dbindex'] = $m[1] ?? $query['dbindex'] ?? '0'; + if (preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['dbindex'] = $m[1]; $params['path'] = substr($params['path'], 0, -\strlen($m[0])); } elseif (isset($params['host'])) { - throw new InvalidArgumentException('Invalid Redis DSN: parameter "dbindex" must be a number.'); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s", the "dbindex" parameter must be a number.', $dsn)); } } @@ -167,115 +165,49 @@ trait RedisTrait } if (!$hosts) { - throw new InvalidArgumentException('Invalid Redis DSN: missing host.'); - } - - if (isset($params['dbindex'], $query['dbindex']) && $params['dbindex'] !== $query['dbindex']) { - throw new InvalidArgumentException('Invalid Redis DSN: path and query "dbindex" parameters mismatch.'); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } $params += $query + $options + self::$defaultConnectionOptions; if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class)) { - throw new CacheException('Redis Sentinel support requires the "predis/predis" package or the "redis" extension v5.2 or higher.'); + throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package or the "redis" extension v5.2 or higher: "%s".', $dsn)); } - if (isset($params['lazy'])) { - $params['lazy'] = filter_var($params['lazy'], \FILTER_VALIDATE_BOOLEAN); - } - $params['redis_cluster'] = filter_var($params['redis_cluster'], \FILTER_VALIDATE_BOOLEAN); - if ($params['redis_cluster'] && isset($params['redis_sentinel'])) { - throw new InvalidArgumentException('Cannot use both "redis_cluster" and "redis_sentinel" at the same time.'); + throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn)); } if (null === $params['class'] && \extension_loaded('redis')) { - $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) && !isset($params['redis_sentinel']) ? \RedisArray::class : \Redis::class); + $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class); } else { $class = $params['class'] ?? \Predis\Client::class; - - if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class)) { - throw new CacheException(sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and ext-redis >= 5.2 not found.', $class)); - } } if (is_a($class, \Redis::class, true)) { $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; $redis = new $class(); - $initializer = static function ($redis) use ($connect, $params, $auth, $hosts, $tls) { - $hostIndex = 0; - do { - $host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path']; - $port = $hosts[$hostIndex]['port'] ?? 0; - $passAuth = \defined('Redis::OPT_NULL_MULTIBULK_AS_NULL') && isset($params['auth']); - $address = false; + $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) { + $host = $hosts[0]['host'] ?? $hosts[0]['path']; + $port = $hosts[0]['port'] ?? 0; - if (isset($hosts[$hostIndex]['host']) && $tls) { - $host = 'tls://'.$host; + if (isset($hosts[0]['host']) && $tls) { + $host = 'tls://'.$host; + } + + if (isset($params['redis_sentinel'])) { + $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']); + + if (!$address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { + throw new InvalidArgumentException(sprintf('Failed to retrieve master information from master name "%s" and address "%s:%d".', $params['redis_sentinel'], $host, $port)); } - if (!isset($params['redis_sentinel'])) { - break; - } - - if (version_compare(phpversion('redis'), '6.0.0', '>=')) { - $options = [ - 'host' => $host, - 'port' => $port, - 'connectTimeout' => (float) $params['timeout'], - 'persistent' => $params['persistent_id'], - 'retryInterval' => (int) $params['retry_interval'], - 'readTimeout' => (float) $params['read_timeout'], - ]; - - if ($passAuth) { - $options['auth'] = $params['auth']; - } - - $sentinel = new \RedisSentinel($options); - } else { - $extra = $passAuth ? [$params['auth']] : []; - - $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); - } - - try { - if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { - [$host, $port] = $address; - } - } catch (\RedisException $e) { - } - } while (++$hostIndex < \count($hosts) && !$address); - - if (isset($params['redis_sentinel']) && !$address) { - throw new InvalidArgumentException(sprintf('Failed to retrieve master information from sentinel "%s".', $params['redis_sentinel'])); + [$host, $port] = $address; } try { - $extra = [ - 'stream' => $params['ssl'] ?? null, - ]; - $booleanStreamOptions = [ - 'allow_self_signed', - 'capture_peer_cert', - 'capture_peer_cert_chain', - 'disable_compression', - 'SNI_enabled', - 'verify_peer', - 'verify_peer_name', - ]; - - foreach ($extra['stream'] ?? [] as $streamOption => $value) { - if (\in_array($streamOption, $booleanStreamOptions, true) && \is_string($value)) { - $extra['stream'][$streamOption] = filter_var($value, \FILTER_VALIDATE_BOOL); - } - } - - if (isset($params['auth'])) { - $extra['auth'] = $params['auth']; - } - @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [$extra] : []); + @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [['stream' => $params['ssl'] ?? null]] : []); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); try { @@ -284,25 +216,22 @@ trait RedisTrait restore_error_handler(); } if (!$isConnected) { - $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error ?? $redis->getLastError() ?? '', $error) ? sprintf(' (%s)', $error[1]) : ''; - throw new InvalidArgumentException('Redis connection failed: '.$error.'.'); + $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : ''; + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.'); } if ((null !== $auth && !$redis->auth($auth)) - // Due to a bug in phpredis we must always select the dbindex if persistent pooling is enabled - // @see https://github.com/phpredis/phpredis/issues/1920 - // @see https://github.com/symfony/symfony/issues/51578 - || (($params['dbindex'] || ('pconnect' === $connect && '0' !== \ini_get('redis.pconnect.pooling_enabled'))) && !$redis->select($params['dbindex'])) + || ($params['dbindex'] && !$redis->select($params['dbindex'])) ) { $e = preg_replace('/^ERR /', '', $redis->getLastError()); - throw new InvalidArgumentException('Redis connection failed: '.$e.'.'); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.'); } if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); } } catch (\RedisException $e) { - throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); } return true; @@ -327,14 +256,14 @@ trait RedisTrait try { $redis = new $class($hosts, $params); } catch (\RedisClusterException $e) { - throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); } if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); } } elseif (is_a($class, \RedisCluster::class, true)) { - $initializer = static function () use ($class, $params, $hosts) { + $initializer = static function () use ($class, $params, $dsn, $hosts) { foreach ($hosts as $i => $host) { switch ($host['scheme']) { case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; @@ -346,7 +275,7 @@ trait RedisTrait try { $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent'], $params['auth'] ?? '', ...\defined('Redis::SCAN_PREFIX') ? [$params['ssl'] ?? null] : []); } catch (\RedisClusterException $e) { - throw new InvalidArgumentException('Redis connection failed: '.$e->getMessage()); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); } if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { @@ -382,15 +311,6 @@ trait RedisTrait if (null !== $auth) { $params['parameters']['password'] = $auth; } - - if (isset($params['ssl'])) { - foreach ($hosts as $i => $host) { - if (!isset($host['ssl'])) { - $hosts[$i]['ssl'] = $params['ssl']; - } - } - } - if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) { $hosts = $hosts[0]; } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) { @@ -399,7 +319,7 @@ trait RedisTrait } $params['exceptions'] = false; - $redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions)); + $redis = new $class($hosts, array_diff_key($params, array_diff_key(self::$defaultConnectionOptions, ['ssl' => null]))); if (isset($params['redis_sentinel'])) { $redis->getConnection()->setSentinelTimeout($params['timeout']); } @@ -412,6 +332,9 @@ trait RedisTrait return $redis; } + /** + * {@inheritdoc} + */ protected function doFetch(array $ids) { if (!$ids) { @@ -420,7 +343,7 @@ trait RedisTrait $result = []; - if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'get' => [$id]; @@ -445,16 +368,22 @@ trait RedisTrait return $result; } + /** + * {@inheritdoc} + */ protected function doHave(string $id) { return (bool) $this->redis->exists($id); } + /** + * {@inheritdoc} + */ protected function doClear(string $namespace) { if ($this->redis instanceof \Predis\ClientInterface) { $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : ''; - $prefixLen = \strlen($prefix ?? ''); + $prefixLen = \strlen($prefix); } $cleared = true; @@ -492,7 +421,7 @@ trait RedisTrait $cursor = null; do { - $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor ?? 0, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); + $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); if (isset($keys[1]) && \is_array($keys[1])) { $cursor = $keys[0]; $keys = $keys[1]; @@ -505,19 +434,22 @@ trait RedisTrait } $this->doDelete($keys); } - } while ($cursor); + } while ($cursor = (int) $cursor); } return $cleared; } + /** + * {@inheritdoc} + */ protected function doDelete(array $ids) { if (!$ids) { return true; } - if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { static $del; $del = $del ?? (class_exists(UNLINK::class) ? 'unlink' : 'del'); @@ -545,6 +477,9 @@ trait RedisTrait return true; } + /** + * {@inheritdoc} + */ protected function doSave(array $values, int $lifetime) { if (!$values = $this->marshaller->marshall($values, $failed)) { @@ -570,12 +505,12 @@ trait RedisTrait return $failed; } - private function pipeline(\Closure $generator, ?object $redis = null): \Generator + private function pipeline(\Closure $generator, object $redis = null): \Generator { $ids = []; $redis = $redis ?? $this->redis; - if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && ($redis->getConnection() instanceof RedisCluster || $redis->getConnection() instanceof Predis2RedisCluster))) { + if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { // phpredis & predis don't support pipelining with RedisCluster // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 @@ -620,11 +555,7 @@ trait RedisTrait if (!$redis instanceof \Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) { $e = new \RedisException($redis->getLastError()); - $results = array_map(function ($v) use ($e) { return false === $v ? $e : $v; }, (array) $results); - } - - if (\is_bool($results)) { - return; + $results = array_map(function ($v) use ($e) { return false === $v ? $e : $v; }, $results); } foreach ($ids as $k => $id) { @@ -637,7 +568,7 @@ trait RedisTrait $hosts = [$this->redis]; if ($this->redis instanceof \Predis\ClientInterface) { $connection = $this->redis->getConnection(); - if (($connection instanceof ClusterInterface || $connection instanceof Predis2ClusterInterface) && $connection instanceof \Traversable) { + if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { $hosts = []; foreach ($connection as $c) { $hosts[] = new \Predis\Client($c); diff --git a/src/vendor/symfony/cache/composer.json b/src/vendor/symfony/cache/composer.json index fdf794fb3..1ebcfc9b3 100644 --- a/src/vendor/symfony/cache/composer.json +++ b/src/vendor/symfony/cache/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/cache", "type": "library", - "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "description": "Provides an extended PSR-6, PSR-16 (and tags) implementation", "keywords": ["caching", "psr6"], "homepage": "https://symfony.com", "license": "MIT", @@ -34,8 +34,8 @@ "require-dev": { "cache/integration-tests": "dev-master", "doctrine/cache": "^1.6|^2.0", - "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1|^2.0", + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1", "psr/simple-cache": "^1.0|^2.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", diff --git a/src/vendor/symfony/deprecation-contracts/LICENSE b/src/vendor/symfony/deprecation-contracts/LICENSE index 0ed3a2465..406242ff2 100644 --- a/src/vendor/symfony/deprecation-contracts/LICENSE +++ b/src/vendor/symfony/deprecation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/src/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php index 81f4e89fd..351dc5131 100644 --- a/src/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php +++ b/src/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -27,5 +27,5 @@ interface EventDispatcherInterface extends PsrEventDispatcherInterface * * @return object The passed $event MUST be returned */ - public function dispatch(object $event, ?string $eventName = null): object; + public function dispatch(object $event, string $eventName = null): object; } diff --git a/src/vendor/symfony/event-dispatcher-contracts/LICENSE b/src/vendor/symfony/event-dispatcher-contracts/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/src/vendor/symfony/event-dispatcher-contracts/LICENSE +++ b/src/vendor/symfony/event-dispatcher-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/src/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index 84d6a08a1..e1d2007fd 100644 --- a/src/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/src/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -42,7 +42,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa private $requestStack; private $currentRequestHash = ''; - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, ?LoggerInterface $logger = null, ?RequestStack $requestStack = null) + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; @@ -75,7 +75,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa { if (isset($this->wrappedListeners[$eventName])) { foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { + if ($wrappedListener->getWrappedListener() === $listener) { $listener = $wrappedListener; unset($this->wrappedListeners[$eventName][$index]); break; @@ -97,7 +97,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa /** * {@inheritdoc} */ - public function getListeners(?string $eventName = null) + public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } @@ -110,8 +110,8 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa // we might have wrapped listeners for the event (if called while dispatching) // in that case get the priority by wrapper if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { + foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { + if ($wrappedListener->getWrappedListener() === $listener) { return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); } } @@ -123,7 +123,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa /** * {@inheritdoc} */ - public function hasListeners(?string $eventName = null) + public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } @@ -131,7 +131,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa /** * {@inheritdoc} */ - public function dispatch(object $event, ?string $eventName = null): object + public function dispatch(object $event, string $eventName = null): object { $eventName = $eventName ?? \get_class($event); @@ -171,7 +171,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa /** * @return array */ - public function getCalledListeners(?Request $request = null) + public function getCalledListeners(Request $request = null) { if (null === $this->callStack) { return []; @@ -192,7 +192,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa /** * @return array */ - public function getNotCalledListeners(?Request $request = null) + public function getNotCalledListeners(Request $request = null) { try { $allListeners = $this->getListeners(); @@ -235,7 +235,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa return $notCalled; } - public function getOrphanedEvents(?Request $request = null): array + public function getOrphanedEvents(Request $request = null): array { if ($request) { return $this->orphanedEvents[spl_object_hash($request)] ?? []; diff --git a/src/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/src/vendor/symfony/event-dispatcher/Debug/WrappedListener.php index 792c17561..3916716ec 100644 --- a/src/vendor/symfony/event-dispatcher/Debug/WrappedListener.php +++ b/src/vendor/symfony/event-dispatcher/Debug/WrappedListener.php @@ -33,7 +33,7 @@ final class WrappedListener private $priority; private static $hasClassStub; - public function __construct($listener, ?string $name, Stopwatch $stopwatch, ?EventDispatcherInterface $dispatcher = null) + public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { $this->listener = $listener; $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); @@ -47,9 +47,9 @@ final class WrappedListener $this->pretty = $this->name.'::'.$listener[1]; } elseif ($listener instanceof \Closure) { $r = new \ReflectionFunction($listener); - if (str_contains($r->name, '{closure')) { + if (str_contains($r->name, '{closure}')) { $this->pretty = $this->name = 'closure'; - } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + } elseif ($class = $r->getClosureScopeClass()) { $this->name = $class->name; $this->pretty = $this->name.'::'.$r->name; } else { @@ -114,12 +114,10 @@ final class WrappedListener $e = $this->stopwatch->start($this->name, 'event_listener'); - try { - ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); - } finally { - if ($e->isStarted()) { - $e->stop(); - } + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); + + if ($e->isStarted()) { + $e->stop(); } if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { diff --git a/src/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/src/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php index 5f44ff090..8eabe7d74 100644 --- a/src/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php @@ -115,18 +115,14 @@ class RegisterListenersPass implements CompilerPassInterface ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); - if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method'])) { - if (!$r->hasMethod('__invoke')) { - throw new InvalidArgumentException(sprintf('None of the "%s" or "__invoke" methods exist for the service "%s". Please define the "method" attribute on "%s" tags.', $event['method'], $id, $this->listenerTag)); - } - + if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { $event['method'] = '__invoke'; } } $dispatcherDefinition = $globalDispatcherDefinition; if (isset($event['dispatcher'])) { - $dispatcherDefinition = $container->findDefinition($event['dispatcher']); + $dispatcherDefinition = $container->getDefinition($event['dispatcher']); } $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); @@ -165,7 +161,7 @@ class RegisterListenersPass implements CompilerPassInterface continue; } - $dispatcherDefinitions[$attributes['dispatcher']] = $container->findDefinition($attributes['dispatcher']); + $dispatcherDefinitions[$attributes['dispatcher']] = $container->getDefinition($attributes['dispatcher']); } if (!$dispatcherDefinitions) { diff --git a/src/vendor/symfony/event-dispatcher/EventDispatcher.php b/src/vendor/symfony/event-dispatcher/EventDispatcher.php index 9c86bd95c..c479a7544 100644 --- a/src/vendor/symfony/event-dispatcher/EventDispatcher.php +++ b/src/vendor/symfony/event-dispatcher/EventDispatcher.php @@ -45,7 +45,7 @@ class EventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function dispatch(object $event, ?string $eventName = null): object + public function dispatch(object $event, string $eventName = null): object { $eventName = $eventName ?? \get_class($event); @@ -65,7 +65,7 @@ class EventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function getListeners(?string $eventName = null) + public function getListeners(string $eventName = null) { if (null !== $eventName) { if (empty($this->listeners[$eventName])) { @@ -108,7 +108,7 @@ class EventDispatcher implements EventDispatcherInterface $v[0] = $v[0](); $v[1] = $v[1] ?? '__invoke'; } - if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { + if ($v === $listener) { return $priority; } } @@ -120,7 +120,7 @@ class EventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function hasListeners(?string $eventName = null) + public function hasListeners(string $eventName = null) { if (null !== $eventName) { return !empty($this->listeners[$eventName]); @@ -164,7 +164,7 @@ class EventDispatcher implements EventDispatcherInterface $v[0] = $v[0](); $v[1] = $v[1] ?? '__invoke'; } - if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { + if ($v === $listener) { unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); } } diff --git a/src/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/src/vendor/symfony/event-dispatcher/EventDispatcherInterface.php index 4b65e5a66..cc324e1c6 100644 --- a/src/vendor/symfony/event-dispatcher/EventDispatcherInterface.php +++ b/src/vendor/symfony/event-dispatcher/EventDispatcherInterface.php @@ -50,7 +50,7 @@ interface EventDispatcherInterface extends ContractsEventDispatcherInterface * * @return array */ - public function getListeners(?string $eventName = null); + public function getListeners(string $eventName = null); /** * Gets the listener priority for a specific event. @@ -66,5 +66,5 @@ interface EventDispatcherInterface extends ContractsEventDispatcherInterface * * @return bool */ - public function hasListeners(?string $eventName = null); + public function hasListeners(string $eventName = null); } diff --git a/src/vendor/symfony/event-dispatcher/GenericEvent.php b/src/vendor/symfony/event-dispatcher/GenericEvent.php index 4ecd29e3b..b32a301ae 100644 --- a/src/vendor/symfony/event-dispatcher/GenericEvent.php +++ b/src/vendor/symfony/event-dispatcher/GenericEvent.php @@ -29,7 +29,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate protected $arguments; /** - * Encapsulate an event with $subject and $arguments. + * Encapsulate an event with $subject and $args. * * @param mixed $subject The subject of the event, usually an object or a callable * @param array $arguments Arguments to store in the event diff --git a/src/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/src/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php index 4e00bfa45..568d79c3a 100644 --- a/src/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ b/src/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -28,7 +28,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function dispatch(object $event, ?string $eventName = null): object + public function dispatch(object $event, string $eventName = null): object { return $this->dispatcher->dispatch($event, $eventName); } @@ -68,7 +68,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function getListeners(?string $eventName = null) + public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } @@ -84,7 +84,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ - public function hasListeners(?string $eventName = null) + public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } diff --git a/src/vendor/symfony/event-dispatcher/LICENSE b/src/vendor/symfony/event-dispatcher/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/src/vendor/symfony/event-dispatcher/LICENSE +++ b/src/vendor/symfony/event-dispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/http-foundation/BinaryFileResponse.php b/src/vendor/symfony/http-foundation/BinaryFileResponse.php index ccfd6389a..4769cab08 100644 --- a/src/vendor/symfony/http-foundation/BinaryFileResponse.php +++ b/src/vendor/symfony/http-foundation/BinaryFileResponse.php @@ -34,7 +34,6 @@ class BinaryFileResponse extends Response protected $offset = 0; protected $maxlen = -1; protected $deleteFileAfterSend = false; - protected $chunkSize = 16 * 1024; /** * @param \SplFileInfo|string $file The file to stream @@ -45,7 +44,7 @@ class BinaryFileResponse extends Response * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set */ - public function __construct($file, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { parent::__construct(null, $status, $headers); @@ -69,7 +68,7 @@ class BinaryFileResponse extends Response * * @deprecated since Symfony 5.2, use __construct() instead. */ - public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { trigger_deprecation('symfony/http-foundation', '5.2', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); @@ -85,7 +84,7 @@ class BinaryFileResponse extends Response * * @throws FileException */ - public function setFile($file, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { if (!$file instanceof File) { if ($file instanceof \SplFileInfo) { @@ -126,22 +125,6 @@ class BinaryFileResponse extends Response return $this->file; } - /** - * Sets the response stream chunk size. - * - * @return $this - */ - public function setChunkSize(int $chunkSize): self - { - if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) { - throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.'); - } - - $this->chunkSize = $chunkSize; - - return $this; - } - /** * Automatically sets the Last-Modified header according the file modification date. * @@ -206,19 +189,15 @@ class BinaryFileResponse extends Response */ public function prepare(Request $request) { - if ($this->isInformational() || $this->isEmpty()) { - parent::prepare($request); - - $this->maxlen = 0; - - return $this; - } - if (!$this->headers->has('Content-Type')) { $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); } - parent::prepare($request); + if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) { + $this->setProtocolVersion('1.1'); + } + + $this->ensureIEOverSSLCompatibility($request); $this->offset = 0; $this->maxlen = -1; @@ -226,7 +205,6 @@ class BinaryFileResponse extends Response if (false === $fileSize = $this->file->getSize()) { return $this; } - $this->headers->remove('Transfer-Encoding'); $this->headers->set('Content-Length', $fileSize); if (!$this->headers->has('Accept-Ranges')) { @@ -244,12 +222,8 @@ class BinaryFileResponse extends Response } if ('x-accel-redirect' === strtolower($type)) { // Do X-Accel-Mapping substitutions. - // @link https://github.com/rack/rack/blob/main/lib/rack/sendfile.rb - // @link https://mattbrictson.com/blog/accelerated-rails-downloads - if (!$request->headers->has('X-Accel-Mapping')) { - throw new \LogicException('The "X-Accel-Mapping" header must be set when "X-Sendfile-Type" is set to "X-Accel-Redirect".'); - } - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping'), ',='); + // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect + $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); foreach ($parts as $part) { [$pathPrefix, $location] = $part; if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { @@ -271,7 +245,7 @@ class BinaryFileResponse extends Response $range = $request->headers->get('Range'); if (str_starts_with($range, 'bytes=')) { - [$start, $end] = explode('-', substr($range, 6), 2) + [1 => 0]; + [$start, $end] = explode('-', substr($range, 6), 2) + [0]; $end = ('' === $end) ? $fileSize - 1 : (int) $end; @@ -300,10 +274,6 @@ class BinaryFileResponse extends Response } } - if ($request->isMethod('HEAD')) { - $this->maxlen = 0; - } - return $this; } @@ -325,49 +295,24 @@ class BinaryFileResponse extends Response */ public function sendContent() { - try { - if (!$this->isSuccessful()) { - return parent::sendContent(); - } + if (!$this->isSuccessful()) { + return parent::sendContent(); + } - if (0 === $this->maxlen) { - return $this; - } + if (0 === $this->maxlen) { + return $this; + } - $out = fopen('php://output', 'w'); - $file = fopen($this->file->getPathname(), 'r'); + $out = fopen('php://output', 'w'); + $file = fopen($this->file->getPathname(), 'r'); - ignore_user_abort(true); + stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); - if (0 !== $this->offset) { - fseek($file, $this->offset); - } + fclose($out); + fclose($file); - $length = $this->maxlen; - while ($length && !feof($file)) { - $read = $length > $this->chunkSize || 0 > $length ? $this->chunkSize : $length; - - if (false === $data = fread($file, $read)) { - break; - } - while ('' !== $data) { - $read = fwrite($out, $data); - if (false === $read || connection_aborted()) { - break 2; - } - if (0 < $length) { - $length -= $read; - } - $data = substr($data, $read); - } - } - - fclose($out); - fclose($file); - } finally { - if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) { - unlink($this->file->getPathname()); - } + if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) { + unlink($this->file->getPathname()); } return $this; diff --git a/src/vendor/symfony/http-foundation/Cookie.php b/src/vendor/symfony/http-foundation/Cookie.php index 3ff93b9c1..b4b26c015 100644 --- a/src/vendor/symfony/http-foundation/Cookie.php +++ b/src/vendor/symfony/http-foundation/Cookie.php @@ -71,7 +71,7 @@ class Cookie return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); } - public static function create(string $name, ?string $value = null, $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self + public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self { return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); } @@ -80,7 +80,7 @@ class Cookie * @param string $name The name of the cookie * @param string|null $value The value of the cookie * @param int|string|\DateTimeInterface $expire The time the cookie expires - * @param string|null $path The path on the server in which the cookie will be available on + * @param string $path The path on the server in which the cookie will be available on * @param string|null $domain The domain that the cookie is available to * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol @@ -89,7 +89,7 @@ class Cookie * * @throws \InvalidArgumentException */ - public function __construct(string $name, ?string $value = null, $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') + public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') { // from PHP source code if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { diff --git a/src/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php b/src/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php index 80a21bf15..9c719aa04 100644 --- a/src/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php +++ b/src/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\HttpFoundation\Exception; /** - * Raised when a session does not exist. This happens in the following cases: + * Raised when a session does not exists. This happens in the following cases: * - the session is not enabled * - attempt to read a session outside a request context (ie. cli script). * @@ -20,7 +20,7 @@ namespace Symfony\Component\HttpFoundation\Exception; */ class SessionNotFoundException extends \LogicException implements RequestExceptionInterface { - public function __construct(string $message = 'There is currently no session available.', int $code = 0, ?\Throwable $previous = null) + public function __construct(string $message = 'There is currently no session available.', int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/src/vendor/symfony/http-foundation/File/File.php b/src/vendor/symfony/http-foundation/File/File.php index 2deb53d6d..d941577d2 100644 --- a/src/vendor/symfony/http-foundation/File/File.php +++ b/src/vendor/symfony/http-foundation/File/File.php @@ -88,7 +88,7 @@ class File extends \SplFileInfo * * @throws FileException if the target file could not be created */ - public function move(string $directory, ?string $name = null) + public function move(string $directory, string $name = null) { $target = $this->getTargetFile($directory, $name); @@ -121,7 +121,7 @@ class File extends \SplFileInfo /** * @return self */ - protected function getTargetFile(string $directory, ?string $name = null) + protected function getTargetFile(string $directory, string $name = null) { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { diff --git a/src/vendor/symfony/http-foundation/File/UploadedFile.php b/src/vendor/symfony/http-foundation/File/UploadedFile.php index 6ff6e51a8..5cfe8c4c2 100644 --- a/src/vendor/symfony/http-foundation/File/UploadedFile.php +++ b/src/vendor/symfony/http-foundation/File/UploadedFile.php @@ -60,7 +60,7 @@ class UploadedFile extends File * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist */ - public function __construct(string $path, string $originalName, ?string $mimeType = null, ?int $error = null, bool $test = false) + public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; @@ -74,7 +74,7 @@ class UploadedFile extends File * Returns the original file name. * * It is extracted from the request from which the file has been uploaded. - * This should not be considered as a safe value to use for a file name on your servers. + * Then it should not be considered as a safe value. * * @return string */ @@ -87,7 +87,7 @@ class UploadedFile extends File * Returns the original file extension. * * It is extracted from the original file name that was uploaded. - * This should not be considered as a safe value to use for a file name on your servers. + * Then it should not be considered as a safe value. * * @return string */ @@ -172,7 +172,7 @@ class UploadedFile extends File * * @throws FileException if, for any reason, the file could not have been moved */ - public function move(string $directory, ?string $name = null) + public function move(string $directory, string $name = null) { if ($this->isValid()) { if ($this->test) { @@ -223,8 +223,8 @@ class UploadedFile extends File */ public static function getMaxFilesize() { - $sizePostMax = self::parseFilesize(\ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize')); + $sizePostMax = self::parseFilesize(ini_get('post_max_size')); + $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); } @@ -253,11 +253,11 @@ class UploadedFile extends File switch (substr($size, -1)) { case 't': $max *= 1024; - // no break + // no break case 'g': $max *= 1024; - // no break + // no break case 'm': $max *= 1024; - // no break + // no break case 'k': $max *= 1024; } diff --git a/src/vendor/symfony/http-foundation/HeaderBag.php b/src/vendor/symfony/http-foundation/HeaderBag.php index 43d5f6327..4683a6840 100644 --- a/src/vendor/symfony/http-foundation/HeaderBag.php +++ b/src/vendor/symfony/http-foundation/HeaderBag.php @@ -67,7 +67,7 @@ class HeaderBag implements \IteratorAggregate, \Countable * * @return array>|array */ - public function all(?string $key = null) + public function all(string $key = null) { if (null !== $key) { return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; @@ -110,7 +110,7 @@ class HeaderBag implements \IteratorAggregate, \Countable * * @return string|null */ - public function get(string $key, ?string $default = null) + public function get(string $key, string $default = null) { $headers = $this->all($key); @@ -197,7 +197,7 @@ class HeaderBag implements \IteratorAggregate, \Countable * * @throws \RuntimeException When the HTTP header is not parseable */ - public function getDate(string $key, ?\DateTime $default = null) + public function getDate(string $key, \DateTime $default = null) { if (null === $value = $this->get($key)) { return $default; diff --git a/src/vendor/symfony/http-foundation/HeaderUtils.php b/src/vendor/symfony/http-foundation/HeaderUtils.php index 110896e17..1d56be080 100644 --- a/src/vendor/symfony/http-foundation/HeaderUtils.php +++ b/src/vendor/symfony/http-foundation/HeaderUtils.php @@ -33,21 +33,17 @@ class HeaderUtils * * Example: * - * HeaderUtils::split('da, en-gb;q=0.8', ',;') + * HeaderUtils::split("da, en-gb;q=0.8", ",;") * // => ['da'], ['en-gb', 'q=0.8']] * * @param string $separators List of characters to split on, ordered by - * precedence, e.g. ',', ';=', or ',;=' + * precedence, e.g. ",", ";=", or ",;=" * * @return array Nested array with as many levels as there are characters in * $separators */ public static function split(string $header, string $separators): array { - if ('' === $separators) { - throw new \InvalidArgumentException('At least one separator must be specified.'); - } - $quotedSeparators = preg_quote($separators, '/'); preg_match_all(' @@ -81,8 +77,8 @@ class HeaderUtils * * Example: * - * HeaderUtils::combine([['foo', 'abc'], ['bar']]) - * // => ['foo' => 'abc', 'bar' => true] + * HeaderUtils::combine([["foo", "abc"], ["bar"]]) + * // => ["foo" => "abc", "bar" => true] */ public static function combine(array $parts): array { @@ -99,13 +95,13 @@ class HeaderUtils /** * Joins an associative array into a string for use in an HTTP header. * - * The key and value of each entry are joined with '=', and all entries + * The key and value of each entry are joined with "=", and all entries * are joined with the specified separator and an additional space (for * readability). Values are quoted if necessary. * * Example: * - * HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',') + * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") * // => 'foo=abc, bar, baz="a b c"' */ public static function toString(array $assoc, string $separator): string @@ -142,7 +138,7 @@ class HeaderUtils * Decodes a quoted string. * * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatim. + * defined in the HTTP specification), it is passed through verbatimly. */ public static function unquote(string $s): string { @@ -256,40 +252,39 @@ class HeaderUtils private static function groupParts(array $matches, string $separators, bool $first = true): array { $separator = $separators[0]; - $separators = substr($separators, 1) ?: ''; + $partSeparators = substr($separators, 1); + $i = 0; - - if ('' === $separators && !$first) { - $parts = ['']; - - foreach ($matches as $match) { - if (!$i && isset($match['separator'])) { - $i = 1; - $parts[1] = ''; - } else { - $parts[$i] .= self::unquote($match[0]); - } - } - - return $parts; - } - - $parts = []; $partMatches = []; - + $previousMatchWasSeparator = false; foreach ($matches as $match) { - if (($match['separator'] ?? null) === $separator) { + if (!$first && $previousMatchWasSeparator && isset($match['separator']) && $match['separator'] === $separator) { + $previousMatchWasSeparator = true; + $partMatches[$i][] = $match; + } elseif (isset($match['separator']) && $match['separator'] === $separator) { + $previousMatchWasSeparator = true; ++$i; } else { + $previousMatchWasSeparator = false; $partMatches[$i][] = $match; } } - foreach ($partMatches as $matches) { - if ('' === $separators && '' !== $unquoted = self::unquote($matches[0][0])) { - $parts[] = $unquoted; - } elseif ($groupedParts = self::groupParts($matches, $separators, false)) { - $parts[] = $groupedParts; + $parts = []; + if ($partSeparators) { + foreach ($partMatches as $matches) { + $parts[] = self::groupParts($matches, $partSeparators, false); + } + } else { + foreach ($partMatches as $matches) { + $parts[] = self::unquote($matches[0][0]); + } + + if (!$first && 2 < \count($parts)) { + $parts = [ + $parts[0], + implode($separator, \array_slice($parts, 1)), + ]; } } diff --git a/src/vendor/symfony/http-foundation/InputBag.php b/src/vendor/symfony/http-foundation/InputBag.php index 356fbbc6f..b36001d8b 100644 --- a/src/vendor/symfony/http-foundation/InputBag.php +++ b/src/vendor/symfony/http-foundation/InputBag.php @@ -29,14 +29,14 @@ final class InputBag extends ParameterBag */ public function get(string $key, $default = null) { - if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { + if (null !== $default && !is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__); } $value = parent::get($key, $this); - if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); + if (null !== $value && $this !== $value && !is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { + trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-string value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); } return $this === $value ? $default : $value; @@ -45,7 +45,7 @@ final class InputBag extends ParameterBag /** * {@inheritdoc} */ - public function all(?string $key = null): array + public function all(string $key = null): array { return parent::all($key); } @@ -76,7 +76,7 @@ final class InputBag extends ParameterBag */ public function set(string $key, $value) { - if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { + if (null !== $value && !is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__); } diff --git a/src/vendor/symfony/http-foundation/IpUtils.php b/src/vendor/symfony/http-foundation/IpUtils.php index 49d9a9d74..24111f1ec 100644 --- a/src/vendor/symfony/http-foundation/IpUtils.php +++ b/src/vendor/symfony/http-foundation/IpUtils.php @@ -73,7 +73,7 @@ class IpUtils return false; } - $cacheKey = $requestIp.'-'.$ip.'-v4'; + $cacheKey = $requestIp.'-'.$ip; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } @@ -86,7 +86,7 @@ class IpUtils [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { - return self::$checkedIps[$cacheKey] = false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); + return self::$checkedIps[$cacheKey] = filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); } if ($netmask < 0 || $netmask > 32) { @@ -126,7 +126,7 @@ class IpUtils return false; } - $cacheKey = $requestIp.'-'.$ip.'-v6'; + $cacheKey = $requestIp.'-'.$ip; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } @@ -135,18 +135,9 @@ class IpUtils throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } - // Check to see if we were given a IP4 $requestIp or $ip by mistake - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - if (str_contains($ip, '/')) { [$address, $netmask] = explode('/', $ip, 2); - if (!filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - if ('0' === $netmask) { return (bool) unpack('n*', @inet_pton($address)); } @@ -155,10 +146,6 @@ class IpUtils return self::$checkedIps[$cacheKey] = false; } } else { - if (!filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - $address = $ip; $netmask = 128; } diff --git a/src/vendor/symfony/http-foundation/JsonResponse.php b/src/vendor/symfony/http-foundation/JsonResponse.php index 51bdf1976..501a6387d 100644 --- a/src/vendor/symfony/http-foundation/JsonResponse.php +++ b/src/vendor/symfony/http-foundation/JsonResponse.php @@ -105,7 +105,7 @@ class JsonResponse extends Response * * @throws \InvalidArgumentException When the callback name is not valid */ - public function setCallback(?string $callback = null) + public function setCallback(string $callback = null) { if (null !== $callback) { // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ diff --git a/src/vendor/symfony/http-foundation/LICENSE b/src/vendor/symfony/http-foundation/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/src/vendor/symfony/http-foundation/LICENSE +++ b/src/vendor/symfony/http-foundation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/http-foundation/ParameterBag.php b/src/vendor/symfony/http-foundation/ParameterBag.php index b542292bc..7d051abe7 100644 --- a/src/vendor/symfony/http-foundation/ParameterBag.php +++ b/src/vendor/symfony/http-foundation/ParameterBag.php @@ -39,7 +39,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @return array */ - public function all(/* ?string $key = null */) + public function all(/*string $key = null*/) { $key = \func_num_args() > 0 ? func_get_arg(0) : null; diff --git a/src/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/src/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php index a6dd993b7..c91d614fe 100644 --- a/src/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php +++ b/src/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php @@ -35,7 +35,9 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface foreach ($limiters as $limiter) { $rateLimit = $limiter->consume(1); - $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit; + if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) { + $minimalRateLimit = $rateLimit; + } } return $minimalRateLimit; @@ -52,20 +54,4 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface * @return LimiterInterface[] a set of limiters using keys extracted from the request */ abstract protected function getLimiters(Request $request): array; - - private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit - { - if ($first->isAccepted() !== $second->isAccepted()) { - return $first->isAccepted() ? $second : $first; - } - - $firstRemainingTokens = $first->getRemainingTokens(); - $secondRemainingTokens = $second->getRemainingTokens(); - - if ($firstRemainingTokens === $secondRemainingTokens) { - return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first; - } - - return $firstRemainingTokens > $secondRemainingTokens ? $second : $first; - } } diff --git a/src/vendor/symfony/http-foundation/RedirectResponse.php b/src/vendor/symfony/http-foundation/RedirectResponse.php index 7b89f0faf..2103280c6 100644 --- a/src/vendor/symfony/http-foundation/RedirectResponse.php +++ b/src/vendor/symfony/http-foundation/RedirectResponse.php @@ -103,7 +103,6 @@ class RedirectResponse extends Response ', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); $this->headers->set('Location', $url); - $this->headers->set('Content-Type', 'text/html; charset=utf-8'); return $this; } diff --git a/src/vendor/symfony/http-foundation/Request.php b/src/vendor/symfony/http-foundation/Request.php index d1103cf8a..d112b1f18 100644 --- a/src/vendor/symfony/http-foundation/Request.php +++ b/src/vendor/symfony/http-foundation/Request.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpFoundation; -use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; use Symfony\Component\HttpFoundation\Exception\JsonException; use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; @@ -192,7 +191,7 @@ class Request protected $session; /** - * @var string|null + * @var string */ protected $locale; @@ -247,9 +246,6 @@ class Request self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX', ]; - /** @var bool */ - private $isIisRewrite = false; - /** * @param array $query The GET parameters * @param array $request The POST parameters @@ -334,8 +330,6 @@ class Request * @param string|resource|null $content The raw body data * * @return static - * - * @throws BadRequestException When the URI is invalid */ public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) { @@ -358,20 +352,7 @@ class Request $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); - if (false === $components = parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri.'#')) { - throw new BadRequestException('Invalid URI.'); - } - - if (false !== ($i = strpos($uri, '\\')) && $i < strcspn($uri, '?#')) { - throw new BadRequestException('Invalid URI: A URI cannot contain a backslash.'); - } - if (\strlen($uri) !== strcspn($uri, "\r\n\t")) { - throw new BadRequestException('Invalid URI: A URI cannot contain CR/LF/TAB characters.'); - } - if ('' !== $uri && (\ord($uri[0]) <= 32 || \ord($uri[-1]) <= 32)) { - throw new BadRequestException('Invalid URI: A URI must not start nor end with ASCII control characters or spaces.'); - } - + $components = parse_url($uri); if (isset($components['host'])) { $server['SERVER_NAME'] = $components['host']; $server['HTTP_HOST'] = $components['host']; @@ -458,16 +439,16 @@ class Request /** * Clones a request and overrides some of its parameters. * - * @param array|null $query The GET parameters - * @param array|null $request The POST parameters - * @param array|null $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array|null $cookies The COOKIE parameters - * @param array|null $files The FILES parameters - * @param array|null $server The SERVER parameters + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters * * @return static */ - public function duplicate(?array $query = null, ?array $request = null, ?array $attributes = null, ?array $cookies = null, ?array $files = null, ?array $server = null) + public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if (null !== $query) { @@ -541,10 +522,10 @@ class Request $cookies = []; foreach ($this->cookies as $k => $v) { - $cookies[] = \is_array($v) ? http_build_query([$k => $v], '', '; ', \PHP_QUERY_RFC3986) : "$k=$v"; + $cookies[] = $k.'='.$v; } - if ($cookies) { + if (!empty($cookies)) { $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; } @@ -581,7 +562,7 @@ class Request $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order'); + $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = [[]]; @@ -1306,7 +1287,7 @@ class Request } if (!preg_match('/^[A-Z]++$/D', $method)) { - throw new SuspiciousOperationException('Invalid HTTP method override.'); + throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); } return $this->method = $method; @@ -1471,7 +1452,7 @@ class Request */ public function getLocale() { - return $this->locale ?? $this->defaultLocale; + return null === $this->locale ? $this->defaultLocale : $this->locale; } /** @@ -1592,9 +1573,9 @@ class Request /** * Gets the request body decoded as array, typically from a JSON payload. * - * @return array - * * @throws JsonException When the body cannot be decoded to an array + * + * @return array */ public function toArray() { @@ -1667,7 +1648,7 @@ class Request * * @return string|null */ - public function getPreferredLanguage(?array $locales = null) + public function getPreferredLanguage(array $locales = null) { $preferredLanguages = $this->getLanguages(); @@ -1708,8 +1689,7 @@ class Request $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); $this->languages = []; - foreach ($languages as $acceptHeaderItem) { - $lang = $acceptHeaderItem->getValue(); + foreach ($languages as $lang => $acceptHeaderItem) { if (str_contains($lang, '-')) { $codes = explode('-', $lang); if ('i' === $codes[0]) { @@ -1747,7 +1727,7 @@ class Request return $this->charsets; } - return $this->charsets = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all())); + return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); } /** @@ -1761,7 +1741,7 @@ class Request return $this->encodings; } - return $this->encodings = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all())); + return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); } /** @@ -1775,7 +1755,7 @@ class Request return $this->acceptableContentTypes; } - return $this->acceptableContentTypes = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all())); + return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); } /** @@ -1824,10 +1804,11 @@ class Request { $requestUri = ''; - if ($this->isIisRewrite() && '' != $this->server->get('UNENCODED_URL')) { + if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); + $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); @@ -2030,13 +2011,7 @@ class Request */ private function getUrlencodedPrefix(string $string, string $prefix): ?string { - if ($this->isIisRewrite()) { - // ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case - // see https://github.com/php/php-src/issues/11981 - if (0 !== stripos(rawurldecode($string), $prefix)) { - return null; - } - } elseif (!str_starts_with(rawurldecode($string), $prefix)) { + if (!str_starts_with(rawurldecode($string), $prefix)) { return null; } @@ -2077,7 +2052,7 @@ class Request return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies); } - private function getTrustedValues(int $type, ?string $ip = null): array + private function getTrustedValues(int $type, string $ip = null): array { $clientValues = []; $forwardedValues = []; @@ -2169,20 +2144,4 @@ class Request // Now the IP chain contains only untrusted proxies and the client IP return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; } - - /** - * Is this IIS with UrlRewriteModule? - * - * This method consumes, caches and removed the IIS_WasUrlRewritten env var, - * so we don't inherit it to sub-requests. - */ - private function isIisRewrite(): bool - { - if (1 === $this->server->getInt('IIS_WasUrlRewritten')) { - $this->isIisRewrite = true; - $this->server->remove('IIS_WasUrlRewritten'); - } - - return $this->isIisRewrite; - } } diff --git a/src/vendor/symfony/http-foundation/RequestMatcher.php b/src/vendor/symfony/http-foundation/RequestMatcher.php index 03ccee97e..f2645f9ae 100644 --- a/src/vendor/symfony/http-foundation/RequestMatcher.php +++ b/src/vendor/symfony/http-foundation/RequestMatcher.php @@ -58,7 +58,7 @@ class RequestMatcher implements RequestMatcherInterface * @param string|string[]|null $ips * @param string|string[]|null $schemes */ - public function __construct(?string $path = null, ?string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, ?int $port = null) + public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) { $this->matchPath($path); $this->matchHost($host); @@ -91,7 +91,7 @@ class RequestMatcher implements RequestMatcherInterface } /** - * Adds a check for the URL port. + * Adds a check for the the URL port. * * @param int|null $port The port number to connect to */ diff --git a/src/vendor/symfony/http-foundation/Response.php b/src/vendor/symfony/http-foundation/Response.php index 6798a04c8..def7f8e70 100644 --- a/src/vendor/symfony/http-foundation/Response.php +++ b/src/vendor/symfony/http-foundation/Response.php @@ -72,7 +72,7 @@ class Response public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725 + public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; public const HTTP_INTERNAL_SERVER_ERROR = 500; public const HTTP_NOT_IMPLEMENTED = 501; public const HTTP_BAD_GATEWAY = 502; @@ -298,7 +298,7 @@ class Response $charset = $this->charset ?: 'UTF-8'; if (!$headers->has('Content-Type')) { $headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif (0 === stripos($headers->get('Content-Type') ?? '', 'text/') && false === stripos($headers->get('Content-Type') ?? '', 'charset')) { + } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { // add the charset $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); } @@ -399,7 +399,6 @@ class Response litespeed_finish_request(); } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { static::closeOutputBuffers(0, true); - flush(); } return $this; @@ -463,7 +462,7 @@ class Response * * @final */ - public function setStatusCode(int $code, ?string $text = null): object + public function setStatusCode(int $code, string $text = null): object { $this->statusCode = $code; if ($this->isInvalid()) { @@ -737,7 +736,7 @@ class Response * * @final */ - public function setExpires(?\DateTimeInterface $date = null): object + public function setExpires(\DateTimeInterface $date = null): object { if (null === $date) { $this->headers->remove('Expires'); @@ -774,10 +773,8 @@ class Response return (int) $this->headers->getCacheControlDirective('max-age'); } - if (null !== $expires = $this->getExpires()) { - $maxAge = (int) $expires->format('U') - (int) $this->getDate()->format('U'); - - return max($maxAge, 0); + if (null !== $this->getExpires()) { + return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); } return null; @@ -821,7 +818,7 @@ class Response * * It returns null when no freshness information is present in the response. * - * When the response's TTL is 0, the response may not be served from cache without first + * When the responses TTL is <= 0, the response may not be served from cache without first * revalidating with the origin. * * @final @@ -830,7 +827,7 @@ class Response { $maxAge = $this->getMaxAge(); - return null !== $maxAge ? max($maxAge - $this->getAge(), 0) : null; + return null !== $maxAge ? $maxAge - $this->getAge() : null; } /** @@ -886,7 +883,7 @@ class Response * * @final */ - public function setLastModified(?\DateTimeInterface $date = null): object + public function setLastModified(\DateTimeInterface $date = null): object { if (null === $date) { $this->headers->remove('Last-Modified'); @@ -924,7 +921,7 @@ class Response * * @final */ - public function setEtag(?string $etag = null, bool $weak = false): object + public function setEtag(string $etag = null, bool $weak = false): object { if (null === $etag) { $this->headers->remove('Etag'); @@ -1217,7 +1214,7 @@ class Response * * @final */ - public function isRedirect(?string $location = null): bool + public function isRedirect(string $location = null): bool { return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); } diff --git a/src/vendor/symfony/http-foundation/ResponseHeaderBag.php b/src/vendor/symfony/http-foundation/ResponseHeaderBag.php index d4c4f393f..1df13fa21 100644 --- a/src/vendor/symfony/http-foundation/ResponseHeaderBag.php +++ b/src/vendor/symfony/http-foundation/ResponseHeaderBag.php @@ -88,7 +88,7 @@ class ResponseHeaderBag extends HeaderBag /** * {@inheritdoc} */ - public function all(?string $key = null) + public function all(string $key = null) { $headers = parent::all(); @@ -186,7 +186,7 @@ class ResponseHeaderBag extends HeaderBag /** * Removes a cookie from the array, but does not unset it in the browser. */ - public function removeCookie(string $name, ?string $path = '/', ?string $domain = null) + public function removeCookie(string $name, ?string $path = '/', string $domain = null) { if (null === $path) { $path = '/'; @@ -239,7 +239,7 @@ class ResponseHeaderBag extends HeaderBag /** * Clears a cookie in the browser. */ - public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null) + public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, string $sameSite = null) { $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); } diff --git a/src/vendor/symfony/http-foundation/ServerBag.php b/src/vendor/symfony/http-foundation/ServerBag.php index 831caa67e..25688d523 100644 --- a/src/vendor/symfony/http-foundation/ServerBag.php +++ b/src/vendor/symfony/http-foundation/ServerBag.php @@ -31,7 +31,7 @@ class ServerBag extends ParameterBag foreach ($this->parameters as $key => $value) { if (str_starts_with($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true) && '' !== $value) { + } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { $headers[$key] = $value; } } @@ -51,7 +51,7 @@ class ServerBag extends ParameterBag * RewriteCond %{HTTP:Authorization} .+ * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] * RewriteCond %{REQUEST_FILENAME} !-f - * RewriteRule ^(.*)$ index.php [QSA,L] + * RewriteRule ^(.*)$ app.php [QSA,L] */ $authorizationHeader = null; diff --git a/src/vendor/symfony/http-foundation/Session/Session.php b/src/vendor/symfony/http-foundation/Session/Session.php index 917920a46..022e3986f 100644 --- a/src/vendor/symfony/http-foundation/Session/Session.php +++ b/src/vendor/symfony/http-foundation/Session/Session.php @@ -39,7 +39,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable private $usageIndex = 0; private $usageReporter; - public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null) + public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null) { $this->storage = $storage ?? new NativeSessionStorage(); $this->usageReporter = $usageReporter; @@ -175,7 +175,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable /** * {@inheritdoc} */ - public function invalidate(?int $lifetime = null) + public function invalidate(int $lifetime = null) { $this->storage->clear(); @@ -185,7 +185,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable /** * {@inheritdoc} */ - public function migrate(bool $destroy = false, ?int $lifetime = null) + public function migrate(bool $destroy = false, int $lifetime = null) { return $this->storage->regenerate($destroy, $lifetime); } diff --git a/src/vendor/symfony/http-foundation/Session/SessionFactory.php b/src/vendor/symfony/http-foundation/Session/SessionFactory.php index bd79282ee..04c4b06a0 100644 --- a/src/vendor/symfony/http-foundation/Session/SessionFactory.php +++ b/src/vendor/symfony/http-foundation/Session/SessionFactory.php @@ -26,7 +26,7 @@ class SessionFactory implements SessionFactoryInterface private $storageFactory; private $usageReporter; - public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, ?callable $usageReporter = null) + public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null) { $this->requestStack = $requestStack; $this->storageFactory = $storageFactory; diff --git a/src/vendor/symfony/http-foundation/Session/SessionInterface.php b/src/vendor/symfony/http-foundation/Session/SessionInterface.php index b73dfd0c3..b2f09fd0d 100644 --- a/src/vendor/symfony/http-foundation/Session/SessionInterface.php +++ b/src/vendor/symfony/http-foundation/Session/SessionInterface.php @@ -59,28 +59,28 @@ interface SessionInterface * Clears all session attributes and flashes and regenerates the * session and deletes the old session from persistence. * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. * * @return bool */ - public function invalidate(?int $lifetime = null); + public function invalidate(int $lifetime = null); /** * Migrates the current session to a new session id while maintaining all * session attributes. * - * @param bool $destroy Whether to delete the old session or leave it to garbage collection - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. + * @param bool $destroy Whether to delete the old session or leave it to garbage collection + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. * * @return bool */ - public function migrate(bool $destroy = false, ?int $lifetime = null); + public function migrate(bool $destroy = false, int $lifetime = null); /** * Force the session to be saved and closed. diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php index 35d7b4b81..bc7b944fc 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -35,8 +35,8 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess public function open($savePath, $sessionName) { $this->sessionName = $sessionName; - if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) { - header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire'))); + if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) { + header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire'))); } return true; @@ -126,7 +126,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess #[\ReturnTypeWillChange] public function destroy($sessionId) { - if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { + if (!headers_sent() && filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { if (!$this->sessionName) { throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); } @@ -141,7 +141,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess */ if (null === $cookie || isset($_COOKIE[$this->sessionName])) { if (\PHP_VERSION_ID < 70300) { - setcookie($this->sessionName, '', 0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); + setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); } else { $params = session_get_cookie_params(); unset($params['lifetime']); diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php index e0ec4d2d9..a5a78eb95 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -77,7 +77,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $this->memcached->touch($this->prefix.$sessionId, $this->getCompatibleTtl()); + $this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); return true; } @@ -87,20 +87,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - return $this->memcached->set($this->prefix.$sessionId, $data, $this->getCompatibleTtl()); - } - - private function getCompatibleTtl(): int - { - $ttl = (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')); - - // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time. - // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct. - if ($ttl > 60 * 60 * 24 * 30) { - $ttl += time(); - } - - return $ttl; + return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); } /** diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php index ef8f71942..8384e79dd 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -121,7 +121,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); + $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); $fields = [ $this->options['time_field'] => new UTCDateTime(), @@ -144,7 +144,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); + $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); $this->getCollection()->updateOne( [$this->options['id_field'] => $sessionId], diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php index 570d4f427..effc9db54 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -19,19 +19,19 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; class NativeFileSessionHandler extends \SessionHandler { /** - * @param string|null $savePath Path of directory to save session files - * Default null will leave setting as defined by PHP. - * '/path', 'N;/path', or 'N;octal-mode;/path + * @param string $savePath Path of directory to save session files + * Default null will leave setting as defined by PHP. + * '/path', 'N;/path', or 'N;octal-mode;/path * * @see https://php.net/session.configuration#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath * @throws \RuntimeException When failing to create the save directory */ - public function __construct(?string $savePath = null) + public function __construct(string $savePath = null) { if (null === $savePath) { - $savePath = \ini_get('session.save_path'); + $savePath = ini_get('session.save_path'); } $baseDir = $savePath; @@ -49,11 +49,7 @@ class NativeFileSessionHandler extends \SessionHandler throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); } - if ($savePath !== \ini_get('session.save_path')) { - ini_set('session.save_path', $savePath); - } - if ('files' !== \ini_get('session.save_handler')) { - ini_set('session.save_handler', 'files'); - } + ini_set('session.save_path', $savePath); + ini_set('session.save_handler', 'files'); } } diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php index f9c5d9b59..067bfcb36 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -112,16 +112,16 @@ class PdoSessionHandler extends AbstractSessionHandler /** * Username when lazy-connect. * - * @var string|null + * @var string */ - private $username = null; + private $username = ''; /** * Password when lazy-connect. * - * @var string|null + * @var string */ - private $password = null; + private $password = ''; /** * Connection options when lazy-connect. @@ -344,7 +344,7 @@ class PdoSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - $maxlifetime = (int) \ini_get('session.gc_maxlifetime'); + $maxlifetime = (int) ini_get('session.gc_maxlifetime'); try { // We use a single MERGE SQL query when supported by the database. @@ -391,14 +391,14 @@ class PdoSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $expiry = time() + (int) \ini_get('session.gc_maxlifetime'); + $expiry = time() + (int) ini_get('session.gc_maxlifetime'); try { $updateStmt = $this->pdo->prepare( "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" ); - $updateStmt->bindValue(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindValue(':expiry', $expiry, \PDO::PARAM_INT); + $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT); $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); $updateStmt->execute(); } catch (\PDOException $e) { @@ -530,8 +530,8 @@ class PdoSessionHandler extends AbstractSessionHandler return $dsn; } } - // If "unix_socket" is not in the query, we continue with the same process as pgsql - // no break + // If "unix_socket" is not in the query, we continue with the same process as pgsql + // no break case 'pgsql': $dsn ?? $dsn = 'pgsql:'; @@ -687,7 +687,7 @@ class PdoSessionHandler extends AbstractSessionHandler throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); } - if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + if (!filter_var(ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // In strict mode, session fixation is not possible: new sessions always start with a unique // random id, so that concurrency is not possible and this code path can be skipped. // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block @@ -935,7 +935,7 @@ class PdoSessionHandler extends AbstractSessionHandler protected function getConnection() { if (null === $this->pdo) { - $this->connect($this->dsn ?: \ini_get('session.save_path')); + $this->connect($this->dsn ?: ini_get('session.save_path')); } return $this->pdo; diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php index 31954e677..9573b3116 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php @@ -79,7 +79,7 @@ class RedisSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data): bool { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data); + $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data); return $result && !$result instanceof ErrorInterface; } @@ -132,6 +132,6 @@ class RedisSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); + return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); } } diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php index 76e4373f8..f3f7b201d 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php @@ -11,10 +11,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; -use Doctrine\DBAL\Configuration; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; -use Doctrine\DBAL\Tools\DsnParser; use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Traits\RedisClusterProxy; use Symfony\Component\Cache\Traits\RedisProxy; @@ -63,7 +60,7 @@ class SessionHandlerFactory case str_starts_with($connection, 'rediss:'): case str_starts_with($connection, 'memcached:'): if (!class_exists(AbstractAdapter::class)) { - throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".'); + throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection)); } $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); @@ -72,18 +69,9 @@ class SessionHandlerFactory case str_starts_with($connection, 'pdo_oci://'): if (!class_exists(DriverManager::class)) { - throw new \InvalidArgumentException('Unsupported PDO OCI DSN. Try running "composer require doctrine/dbal".'); + throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection)); } - $connection[3] = '-'; - $params = class_exists(DsnParser::class) ? (new DsnParser())->parse($connection) : ['url' => $connection]; - $config = new Configuration(); - if (class_exists(DefaultSchemaManagerFactory::class)) { - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - } - - $connection = DriverManager::getConnection($params, $config); - // The condition should be removed once support for DBAL <3.3 is dropped - $connection = method_exists($connection, 'getNativeConnection') ? $connection->getNativeConnection() : $connection->getWrappedConnection(); + $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection(); // no break; case str_starts_with($connection, 'mssql://'): diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/src/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php index f7c385f64..0461e997e 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php @@ -30,16 +30,6 @@ class StrictSessionHandler extends AbstractSessionHandler $this->handler = $handler; } - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @internal - */ - public function isWrapper(): bool - { - return $this->handler instanceof \SessionHandler; - } - /** * @return bool */ diff --git a/src/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/src/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php index 3e10f6dbc..1bfce5520 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -95,12 +95,12 @@ class MetadataBag implements SessionBagInterface /** * Stamps a new session's metadata. * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. */ - public function stampNew(?int $lifetime = null) + public function stampNew(int $lifetime = null) { $this->stampCreated($lifetime); } @@ -158,10 +158,10 @@ class MetadataBag implements SessionBagInterface $this->name = $name; } - private function stampCreated(?int $lifetime = null): void + private function stampCreated(int $lifetime = null): void { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); + $this->meta[self::LIFETIME] = $lifetime ?? (int) ini_get('session.cookie_lifetime'); } } diff --git a/src/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/src/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php index c6a28b1a4..c5c2bb073 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php @@ -62,7 +62,7 @@ class MockArraySessionStorage implements SessionStorageInterface */ protected $bags = []; - public function __construct(string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) + public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); @@ -94,7 +94,7 @@ class MockArraySessionStorage implements SessionStorageInterface /** * {@inheritdoc} */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) + public function regenerate(bool $destroy = false, int $lifetime = null) { if (!$this->started) { $this->start(); @@ -204,7 +204,7 @@ class MockArraySessionStorage implements SessionStorageInterface return $this->started; } - public function setMetadataBag(?MetadataBag $bag = null) + public function setMetadataBag(MetadataBag $bag = null) { if (null === $bag) { $bag = new MetadataBag(); @@ -226,11 +226,14 @@ class MockArraySessionStorage implements SessionStorageInterface /** * Generates a session ID. * + * This doesn't need to be particularly cryptographically secure since this is just + * a mock. + * * @return string */ protected function generateId() { - return bin2hex(random_bytes(16)); + return hash('sha256', uniqid('ss_mock_', true)); } protected function loadSession() diff --git a/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php index 8aeb9724c..8e32a45e3 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php @@ -30,7 +30,7 @@ class MockFileSessionStorage extends MockArraySessionStorage /** * @param string|null $savePath Path of directory to save session files */ - public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) + public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { if (null === $savePath) { $savePath = sys_get_temp_dir(); @@ -68,7 +68,7 @@ class MockFileSessionStorage extends MockArraySessionStorage /** * {@inheritdoc} */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) + public function regenerate(bool $destroy = false, int $lifetime = null) { if (!$this->started) { $this->start(); diff --git a/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php index 900fa7cfa..d0da1e169 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php @@ -28,7 +28,7 @@ class MockFileSessionStorageFactory implements SessionStorageFactoryInterface /** * @see MockFileSessionStorage constructor. */ - public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) + public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->savePath = $savePath; $this->name = $name; diff --git a/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php index e7b42ed0b..02467da9e 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @@ -97,7 +97,7 @@ class NativeSessionStorage implements SessionStorageInterface * * @param AbstractProxy|\SessionHandlerInterface|null $handler */ - public function __construct(array $options = [], $handler = null, ?MetadataBag $metaBag = null) + public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); @@ -141,46 +141,10 @@ class NativeSessionStorage implements SessionStorageInterface throw new \RuntimeException('Failed to start the session: already started by PHP.'); } - if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { + if (filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } - $sessionId = $_COOKIE[session_name()] ?? null; - /* - * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`. - * - * ---------- Part 1 - * - * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character. - * Allowed values are integers such as: - * - 4 for range `a-f0-9` - * - 5 for range `a-v0-9` - * - 6 for range `a-zA-Z0-9,-` - * - * ---------- Part 2 - * - * The part `{22,250}` is related to the PHP ini directive `session.sid_length`. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length. - * Allowed values are integers between 22 and 256, but we use 250 for the max. - * - * Where does the 250 come from? - * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255. - * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250. - * - * ---------- Conclusion - * - * The parts 1 and 2 prevent the warning below: - * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.` - * - * The part 2 prevents the warning below: - * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).` - */ - if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) { - // the session ID in the header is invalid, create a new one - session_id(session_create_id()); - } - // ok to try and start the session if (!session_start()) { throw new \RuntimeException('Failed to start the session.'); @@ -233,7 +197,7 @@ class NativeSessionStorage implements SessionStorageInterface /** * {@inheritdoc} */ - public function regenerate(bool $destroy = false, ?int $lifetime = null) + public function regenerate(bool $destroy = false, int $lifetime = null) { // Cannot regenerate the session ID for non-active sessions. if (\PHP_SESSION_ACTIVE !== session_status()) { @@ -244,7 +208,7 @@ class NativeSessionStorage implements SessionStorageInterface return false; } - if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) { + if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) { $this->save(); ini_set('session.cookie_lifetime', $lifetime); $this->start(); @@ -279,7 +243,7 @@ class NativeSessionStorage implements SessionStorageInterface unset($_SESSION[$key]); } } - if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { + if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { unset($_SESSION[$key]); } @@ -355,7 +319,7 @@ class NativeSessionStorage implements SessionStorageInterface return $this->bags[$name]; } - public function setMetadataBag(?MetadataBag $metaBag = null) + public function setMetadataBag(MetadataBag $metaBag = null) { if (null === $metaBag) { $metaBag = new MetadataBag(); @@ -455,10 +419,9 @@ class NativeSessionStorage implements SessionStorageInterface */ public function setSaveHandler($saveHandler = null) { - if (!$saveHandler instanceof AbstractProxy - && !$saveHandler instanceof \SessionHandlerInterface - && null !== $saveHandler - ) { + if (!$saveHandler instanceof AbstractProxy && + !$saveHandler instanceof \SessionHandlerInterface && + null !== $saveHandler) { throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); } @@ -487,7 +450,7 @@ class NativeSessionStorage implements SessionStorageInterface * PHP takes the return value from the read() handler, unserializes it * and populates $_SESSION with the result automatically. */ - protected function loadSession(?array &$session = null) + protected function loadSession(array &$session = null) { if (null === $session) { $session = &$_SESSION; diff --git a/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php index 48e65267e..a7d7411ff 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php @@ -29,7 +29,7 @@ class NativeSessionStorageFactory implements SessionStorageFactoryInterface /** * @see NativeSessionStorage constructor. */ - public function __construct(array $options = [], $handler = null, ?MetadataBag $metaBag = null, bool $secure = false) + public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null, bool $secure = false) { $this->options = $options; $this->handler = $handler; diff --git a/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php index 855d5e111..72dbef134 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php @@ -23,7 +23,7 @@ class PhpBridgeSessionStorage extends NativeSessionStorage /** * @param AbstractProxy|\SessionHandlerInterface|null $handler */ - public function __construct($handler = null, ?MetadataBag $metaBag = null) + public function __construct($handler = null, MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); diff --git a/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php index aa9326322..173ef71de 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php @@ -28,7 +28,7 @@ class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface /** * @see PhpBridgeSessionStorage constructor. */ - public function __construct($handler = null, ?MetadataBag $metaBag = null, bool $secure = false) + public function __construct($handler = null, MetadataBag $metaBag = null, bool $secure = false) { $this->handler = $handler; $this->metaBag = $metaBag; diff --git a/src/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php index 0defa4a7a..9b0cdeb7f 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -11,8 +11,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; - /** * @author Drak */ @@ -24,7 +22,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf { $this->handler = $handler; $this->wrapper = $handler instanceof \SessionHandler; - $this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user'; + $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; } /** diff --git a/src/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/src/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php index 70b7c6a15..b7f66e7c7 100644 --- a/src/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ b/src/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php @@ -80,17 +80,17 @@ interface SessionStorageInterface * Otherwise session data could get lost again for concurrent requests with the * new ID. One result could be that you get logged out after just logging in. * - * @param bool $destroy Destroy session when regenerating? - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. + * @param bool $destroy Destroy session when regenerating? + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. * * @return bool * * @throws \RuntimeException If an error occurs while regenerating this storage */ - public function regenerate(bool $destroy = false, ?int $lifetime = null); + public function regenerate(bool $destroy = false, int $lifetime = null); /** * Force the session to be saved and closed. diff --git a/src/vendor/symfony/http-foundation/StreamedResponse.php b/src/vendor/symfony/http-foundation/StreamedResponse.php index b42330dcd..676cd6687 100644 --- a/src/vendor/symfony/http-foundation/StreamedResponse.php +++ b/src/vendor/symfony/http-foundation/StreamedResponse.php @@ -30,7 +30,7 @@ class StreamedResponse extends Response protected $streamed; private $headersSent; - public function __construct(?callable $callback = null, int $status = 200, array $headers = []) + public function __construct(callable $callback = null, int $status = 200, array $headers = []) { parent::__construct(null, $status, $headers); @@ -114,9 +114,9 @@ class StreamedResponse extends Response /** * {@inheritdoc} * - * @return $this - * * @throws \LogicException when the content is not null + * + * @return $this */ public function setContent(?string $content) { diff --git a/src/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/src/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php index 939925b98..554e1a160 100644 --- a/src/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php +++ b/src/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php @@ -22,7 +22,7 @@ final class ResponseCookieValueSame extends Constraint private $path; private $domain; - public function __construct(string $name, string $value, string $path = '/', ?string $domain = null) + public function __construct(string $name, string $value, string $path = '/', string $domain = null) { $this->name = $name; $this->value = $value; @@ -59,7 +59,7 @@ final class ResponseCookieValueSame extends Constraint return false; } - return $this->value === (string) $cookie->getValue(); + return $this->value === $cookie->getValue(); } /** diff --git a/src/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/src/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php index 9d6e58c8d..eae9e271b 100644 --- a/src/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php +++ b/src/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php @@ -21,7 +21,7 @@ final class ResponseHasCookie extends Constraint private $path; private $domain; - public function __construct(string $name, string $path = '/', ?string $domain = null) + public function __construct(string $name, string $path = '/', string $domain = null) { $this->name = $name; $this->path = $path; diff --git a/src/vendor/symfony/http-foundation/UrlHelper.php b/src/vendor/symfony/http-foundation/UrlHelper.php index 90659947d..c15f101cd 100644 --- a/src/vendor/symfony/http-foundation/UrlHelper.php +++ b/src/vendor/symfony/http-foundation/UrlHelper.php @@ -12,7 +12,6 @@ namespace Symfony\Component\HttpFoundation; use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; /** * A helper service for manipulating URLs within and outside the request scope. @@ -24,15 +23,8 @@ final class UrlHelper private $requestStack; private $requestContext; - /** - * @param RequestContextAwareInterface|RequestContext|null $requestContext - */ - public function __construct(RequestStack $requestStack, $requestContext = null) + public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) { - if (null !== $requestContext && !$requestContext instanceof RequestContext && !$requestContext instanceof RequestContextAwareInterface) { - throw new \TypeError(__METHOD__.': Argument #2 ($requestContext) must of type Symfony\Component\Routing\RequestContextAwareInterface|Symfony\Component\Routing\RequestContext|null, '.get_debug_type($requestContext).' given.'); - } - $this->requestStack = $requestStack; $this->requestContext = $requestContext; } @@ -81,36 +73,28 @@ final class UrlHelper private function getAbsoluteUrlFromContext(string $path): string { - if (null === $context = $this->requestContext) { + if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { return $path; } - if ($context instanceof RequestContextAwareInterface) { - $context = $context->getContext(); - } - - if ('' === $host = $context->getHost()) { - return $path; - } - - $scheme = $context->getScheme(); + $scheme = $this->requestContext->getScheme(); $port = ''; - if ('http' === $scheme && 80 !== $context->getHttpPort()) { - $port = ':'.$context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $context->getHttpsPort()) { - $port = ':'.$context->getHttpsPort(); + if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { + $port = ':'.$this->requestContext->getHttpPort(); + } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { + $port = ':'.$this->requestContext->getHttpsPort(); } if ('#' === $path[0]) { - $queryString = $context->getQueryString(); - $path = $context->getPathInfo().($queryString ? '?'.$queryString : '').$path; + $queryString = $this->requestContext->getQueryString(); + $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; } elseif ('?' === $path[0]) { - $path = $context->getPathInfo().$path; + $path = $this->requestContext->getPathInfo().$path; } if ('/' !== $path[0]) { - $path = rtrim($context->getBaseUrl(), '/').'/'.$path; + $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; } return $scheme.'://'.$host.$port.$path; diff --git a/src/vendor/symfony/http-foundation/composer.json b/src/vendor/symfony/http-foundation/composer.json index a2e43a99c..d54bbfd16 100644 --- a/src/vendor/symfony/http-foundation/composer.json +++ b/src/vendor/symfony/http-foundation/composer.json @@ -22,13 +22,10 @@ "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "predis/predis": "^1.0|^2.0", + "predis/predis": "~1.0", "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" + "symfony/expression-language": "^4.4|^5.0|^6.0" }, "suggest" : { "symfony/mime": "To use the file extension guesser" diff --git a/src/vendor/symfony/polyfill-mbstring/LICENSE b/src/vendor/symfony/polyfill-mbstring/LICENSE index 6e3afce69..4cd8bdd30 100644 --- a/src/vendor/symfony/polyfill-mbstring/LICENSE +++ b/src/vendor/symfony/polyfill-mbstring/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-present Fabien Potencier +Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/polyfill-mbstring/Mbstring.php b/src/vendor/symfony/polyfill-mbstring/Mbstring.php index 31e36a368..b65c54a6b 100644 --- a/src/vendor/symfony/polyfill-mbstring/Mbstring.php +++ b/src/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -48,11 +48,6 @@ namespace Symfony\Polyfill\Mbstring; * - mb_strstr - Finds first occurrence of a string within another * - mb_strwidth - Return width of string * - mb_substr_count - Count the number of substring occurrences - * - mb_ucfirst - Make a string's first character uppercase - * - mb_lcfirst - Make a string's first character lowercase - * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string - * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string - * - mb_rtrim - Strip whitespace (or other characters) from the end of a string * * Not implemented: * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) @@ -74,7 +69,7 @@ final class Mbstring { public const MB_CASE_FOLD = \PHP_INT_MAX; - private const SIMPLE_CASE_FOLD = [ + private const CASE_FOLD = [ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], ]; @@ -85,16 +80,7 @@ final class Mbstring public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { - if (\is_array($s)) { - $r = []; - foreach ($s as $str) { - $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding); - } - - return $r; - } - - if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { + if (\is_array($fromEncoding) || ($fromEncoding !== null && false !== strpos($fromEncoding, ','))) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); @@ -116,7 +102,7 @@ final class Mbstring $fromEncoding = 'Windows-1252'; } if ('UTF-8' !== $fromEncoding) { - $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s); } return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); @@ -127,7 +113,7 @@ final class Mbstring $fromEncoding = 'UTF-8'; } - return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s); } public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) @@ -144,7 +130,7 @@ final class Mbstring public static function mb_decode_mimeheader($s) { - return iconv_mime_decode($s, 2, self::$internalEncoding); + return \iconv_mime_decode($s, 2, self::$internalEncoding); } public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) @@ -154,7 +140,7 @@ final class Mbstring public static function mb_decode_numericentity($s, $convmap, $encoding = null) { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -164,7 +150,7 @@ final class Mbstring return false; } - if (null !== $encoding && !\is_scalar($encoding)) { + if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return ''; // Instead of null (cf. mb_encode_numericentity). @@ -180,10 +166,10 @@ final class Mbstring if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $cnt = floor(\count($convmap) / 4) * 4; @@ -209,12 +195,12 @@ final class Mbstring return $s; } - return iconv('UTF-8', $encoding.'//IGNORE', $s); + return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -224,13 +210,13 @@ final class Mbstring return false; } - if (null !== $encoding && !\is_scalar($encoding)) { + if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; // Instead of '' (cf. mb_decode_numericentity). } - if (null !== $is_hex && !\is_scalar($is_hex)) { + if (null !== $is_hex && !is_scalar($is_hex)) { trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -246,10 +232,10 @@ final class Mbstring if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; @@ -279,7 +265,7 @@ final class Mbstring return $result; } - return iconv('UTF-8', $encoding.'//IGNORE', $result); + return \iconv('UTF-8', $encoding.'//IGNORE', $result); } public static function mb_convert_case($s, $mode, $encoding = null) @@ -294,10 +280,10 @@ final class Mbstring if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } if (\MB_CASE_TITLE == $mode) { @@ -315,11 +301,7 @@ final class Mbstring $map = $upper; } else { if (self::MB_CASE_FOLD === $mode) { - static $caseFolding = null; - if (null === $caseFolding) { - $caseFolding = self::getData('caseFolding'); - } - $s = strtr($s, $caseFolding); + $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); } static $lower = null; @@ -361,7 +343,7 @@ final class Mbstring return $s; } - return iconv('UTF-8', $encoding.'//IGNORE', $s); + return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_internal_encoding($encoding = null) @@ -372,7 +354,7 @@ final class Mbstring $normalizedEncoding = self::getEncoding($encoding); - if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { + if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) { self::$internalEncoding = $normalizedEncoding; return true; @@ -431,20 +413,7 @@ final class Mbstring $encoding = self::$internalEncoding; } - if (!\is_array($var)) { - return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); - } - - foreach ($var as $key => $value) { - if (!self::mb_check_encoding($key, $encoding)) { - return false; - } - if (!self::mb_check_encoding($value, $encoding)) { - return false; - } - } - - return true; + return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var); } public static function mb_detect_encoding($str, $encodingList = null, $strict = false) @@ -519,7 +488,7 @@ final class Mbstring return \strlen($s); } - return @iconv_strlen($s, $encoding); + return @\iconv_strlen($s, $encoding); } public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) @@ -540,7 +509,7 @@ final class Mbstring return 0; } - return iconv_strpos($haystack, $needle, $offset, $encoding); + return \iconv_strpos($haystack, $needle, $offset, $encoding); } public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) @@ -564,7 +533,7 @@ final class Mbstring } $pos = '' !== $needle || 80000 > \PHP_VERSION_ID - ? iconv_strrpos($haystack, $needle, $encoding) + ? \iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding); return false !== $pos ? $offset + $pos : false; @@ -572,7 +541,7 @@ final class Mbstring public static function mb_str_split($string, $split_length = 1, $encoding = null) { - if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { + if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); return null; @@ -581,7 +550,6 @@ final class Mbstring if (1 > $split_length = (int) $split_length) { if (80000 > \PHP_VERSION_ID) { trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); - return false; } @@ -600,7 +568,7 @@ final class Mbstring } $rx .= '.{'.$split_length.'})/us'; - return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); } $result = []; @@ -649,7 +617,7 @@ final class Mbstring } if ($start < 0) { - $start = iconv_strlen($s, $encoding) + $start; + $start = \iconv_strlen($s, $encoding) + $start; if ($start < 0) { $start = 0; } @@ -658,21 +626,19 @@ final class Mbstring if (null === $length) { $length = 2147483647; } elseif ($length < 0) { - $length = iconv_strlen($s, $encoding) + $length - $start; + $length = \iconv_strlen($s, $encoding) + $length - $start; if ($length < 0) { return ''; } } - return (string) iconv_substr($s, $start, $length, $encoding); + return (string) \iconv_substr($s, $start, $length, $encoding); } public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { - [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ - self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), - self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), - ]); + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strpos($haystack, $needle, $offset, $encoding); } @@ -691,7 +657,7 @@ final class Mbstring $pos = strrpos($haystack, $needle); } else { $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); + $pos = \iconv_strrpos($haystack, $needle, $encoding); } return self::getSubpart($pos, $part, $haystack, $encoding); @@ -707,11 +673,8 @@ final class Mbstring public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { - $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); - $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); - - $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); - $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strrpos($haystack, $needle, $offset, $encoding); } @@ -773,12 +736,12 @@ final class Mbstring $encoding = self::getEncoding($encoding); if ('UTF-8' !== $encoding) { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); - return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + return ($wide << 1) + \iconv_strlen($s, 'UTF-8'); } public static function mb_substr_count($haystack, $needle, $encoding = null) @@ -834,69 +797,6 @@ final class Mbstring return $code; } - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string - { - if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { - throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); - } - - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); - } - - if (self::mb_strlen($pad_string, $encoding) <= 0) { - throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); - } - - $paddingRequired = $length - self::mb_strlen($string, $encoding); - - if ($paddingRequired < 1) { - return $string; - } - - switch ($pad_type) { - case \STR_PAD_LEFT: - return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; - case \STR_PAD_RIGHT: - return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); - default: - $leftPaddingLength = floor($paddingRequired / 2); - $rightPaddingLength = $paddingRequired - $leftPaddingLength; - - return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); - } - } - - public static function mb_ucfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - public static function mb_lcfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - private static function getSubpart($pos, $part, $haystack, $encoding) { if (false === $pos) { @@ -970,76 +870,4 @@ final class Mbstring return $encoding; } - - public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__); - } - - private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given'); - } - - if ('' === $characters) { - return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding); - } - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $string)) { - $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string); - } - if (null !== $characters && !preg_match('//u', $characters)) { - $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters); - } - } else { - $string = iconv($encoding, 'UTF-8//IGNORE', $string); - - if (null !== $characters) { - $characters = iconv($encoding, 'UTF-8//IGNORE', $characters); - } - } - - if (null === $characters) { - $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}"; - } else { - $characters = preg_quote($characters); - } - - $string = preg_replace(sprintf($regex, $characters), '', $string); - - if (null === $encoding) { - return $string; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $string); - } - - private static function assertEncoding(string $encoding, string $errorFormat): void - { - try { - $validEncoding = @self::mb_check_encoding('', $encoding); - } catch (\ValueError $e) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - - // BC for PHP 7.3 and lower - if (!$validEncoding) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - } } diff --git a/src/vendor/symfony/polyfill-mbstring/README.md b/src/vendor/symfony/polyfill-mbstring/README.md index 478b40da2..4efb599d8 100644 --- a/src/vendor/symfony/polyfill-mbstring/README.md +++ b/src/vendor/symfony/polyfill-mbstring/README.md @@ -5,7 +5,7 @@ This component provides a partial, native PHP implementation for the [Mbstring](https://php.net/mbstring) extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/src/vendor/symfony/polyfill-mbstring/bootstrap.php b/src/vendor/symfony/polyfill-mbstring/bootstrap.php index ff51ae079..1fedd1f7c 100644 --- a/src/vendor/symfony/polyfill-mbstring/bootstrap.php +++ b/src/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -132,31 +132,6 @@ if (!function_exists('mb_str_split')) { function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } } -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - - if (extension_loaded('mbstring')) { return; } diff --git a/src/vendor/symfony/polyfill-mbstring/bootstrap80.php b/src/vendor/symfony/polyfill-mbstring/bootstrap80.php index 5236e6dcc..82f5ac4d0 100644 --- a/src/vendor/symfony/polyfill-mbstring/bootstrap80.php +++ b/src/vendor/symfony/polyfill-mbstring/bootstrap80.php @@ -93,7 +93,7 @@ if (!function_exists('mb_strstr')) { function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_get_info')) { - function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); } + function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } } if (!function_exists('mb_http_output')) { function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } @@ -128,30 +128,6 @@ if (!function_exists('mb_str_split')) { function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } } -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - if (extension_loaded('mbstring')) { return; } diff --git a/src/vendor/symfony/polyfill-mbstring/composer.json b/src/vendor/symfony/polyfill-mbstring/composer.json index daa07f86b..1fa21ca16 100644 --- a/src/vendor/symfony/polyfill-mbstring/composer.json +++ b/src/vendor/symfony/polyfill-mbstring/composer.json @@ -16,8 +16,7 @@ } ], "require": { - "php": ">=7.2", - "ext-iconv": "*" + "php": ">=7.1" }, "provide": { "ext-mbstring": "*" @@ -31,6 +30,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/src/vendor/symfony/polyfill-php72/LICENSE b/src/vendor/symfony/polyfill-php72/LICENSE new file mode 100644 index 000000000..4cd8bdd30 --- /dev/null +++ b/src/vendor/symfony/polyfill-php72/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +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. diff --git a/src/vendor/symfony/polyfill-php72/Php72.php b/src/vendor/symfony/polyfill-php72/Php72.php new file mode 100644 index 000000000..5e20d5bf8 --- /dev/null +++ b/src/vendor/symfony/polyfill-php72/Php72.php @@ -0,0 +1,217 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php72; + +/** + * @author Nicolas Grekas + * @author Dariusz Rumiński + * + * @internal + */ +final class Php72 +{ + private static $hashMask; + + public static function utf8_encode($s) + { + $s .= $s; + $len = \strlen($s); + + for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { + switch (true) { + case $s[$i] < "\x80": $s[$j] = $s[$i]; break; + case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; + default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; + } + } + + return substr($s, 0, $j); + } + + public static function utf8_decode($s) + { + $s = (string) $s; + $len = \strlen($s); + + for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { + switch ($s[$i] & "\xF0") { + case "\xC0": + case "\xD0": + $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); + $s[$j] = $c < 256 ? \chr($c) : '?'; + break; + + case "\xF0": + ++$i; + // no break + + case "\xE0": + $s[$j] = '?'; + $i += 2; + break; + + default: + $s[$j] = $s[$i]; + } + } + + return substr($s, 0, $j); + } + + public static function php_os_family() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + return 'Windows'; + } + + $map = [ + 'Darwin' => 'Darwin', + 'DragonFly' => 'BSD', + 'FreeBSD' => 'BSD', + 'NetBSD' => 'BSD', + 'OpenBSD' => 'BSD', + 'Linux' => 'Linux', + 'SunOS' => 'Solaris', + ]; + + return isset($map[\PHP_OS]) ? $map[\PHP_OS] : 'Unknown'; + } + + public static function spl_object_id($object) + { + if (null === self::$hashMask) { + self::initHashMask(); + } + if (null === $hash = spl_object_hash($object)) { + return; + } + + // On 32-bit systems, PHP_INT_SIZE is 4, + return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); + } + + public static function sapi_windows_vt100_support($stream, $enable = null) + { + if (!\is_resource($stream)) { + trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); + + return false; + } + + $meta = stream_get_meta_data($stream); + + if ('STDIO' !== $meta['stream_type']) { + trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', \E_USER_WARNING); + + return false; + } + + // We cannot actually disable vt100 support if it is set + if (false === $enable || !self::stream_isatty($stream)) { + return false; + } + + // The native function does not apply to stdin + $meta = array_map('strtolower', $meta); + $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; + + return !$stdin + && (false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM')); + } + + public static function stream_isatty($stream) + { + if (!\is_resource($stream)) { + trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); + + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + return \function_exists('posix_isatty') && @posix_isatty($stream); + } + + private static function initHashMask() + { + $obj = (object) []; + self::$hashMask = -1; + + // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below + $obFuncs = ['ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush']; + foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? \DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { + if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { + $frame['line'] = 0; + break; + } + } + if (!empty($frame['line'])) { + ob_start(); + debug_zval_dump($obj); + self::$hashMask = (int) substr(ob_get_clean(), 17); + } + + self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = $encoding ?? mb_internal_encoding()) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if (null === $encoding) { + $s = mb_convert_encoding($s, 'UTF-8'); + } elseif ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } +} diff --git a/src/vendor/symfony/polyfill-php72/README.md b/src/vendor/symfony/polyfill-php72/README.md new file mode 100644 index 000000000..59dec8a23 --- /dev/null +++ b/src/vendor/symfony/polyfill-php72/README.md @@ -0,0 +1,28 @@ +Symfony Polyfill / Php72 +======================== + +This component provides functions added to PHP 7.2 core: + +- [`spl_object_id`](https://php.net/spl_object_id) +- [`stream_isatty`](https://php.net/stream_isatty) + +On Windows only: + +- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) + +Moved to core since 7.2 (was in the optional XML extension earlier): + +- [`utf8_encode`](https://php.net/utf8_encode) +- [`utf8_decode`](https://php.net/utf8_decode) + +Also, it provides constants added to PHP 7.2: +- [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig) +- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/src/vendor/symfony/polyfill-php72/bootstrap.php b/src/vendor/symfony/polyfill-php72/bootstrap.php new file mode 100644 index 000000000..b5c92d4c7 --- /dev/null +++ b/src/vendor/symfony/polyfill-php72/bootstrap.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php72 as p; + +if (\PHP_VERSION_ID >= 70200) { + return; +} + +if (!defined('PHP_FLOAT_DIG')) { + define('PHP_FLOAT_DIG', 15); +} +if (!defined('PHP_FLOAT_EPSILON')) { + define('PHP_FLOAT_EPSILON', 2.2204460492503E-16); +} +if (!defined('PHP_FLOAT_MIN')) { + define('PHP_FLOAT_MIN', 2.2250738585072E-308); +} +if (!defined('PHP_FLOAT_MAX')) { + define('PHP_FLOAT_MAX', 1.7976931348623157E+308); +} +if (!defined('PHP_OS_FAMILY')) { + define('PHP_OS_FAMILY', p\Php72::php_os_family()); +} + +if ('\\' === \DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { + function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } +} +if (!function_exists('stream_isatty')) { + function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } +} +if (!function_exists('utf8_encode')) { + function utf8_encode($string) { return p\Php72::utf8_encode($string); } +} +if (!function_exists('utf8_decode')) { + function utf8_decode($string) { return p\Php72::utf8_decode($string); } +} +if (!function_exists('spl_object_id')) { + function spl_object_id($object) { return p\Php72::spl_object_id($object); } +} +if (!function_exists('mb_ord')) { + function mb_ord($string, $encoding = null) { return p\Php72::mb_ord($string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr($codepoint, $encoding = null) { return p\Php72::mb_chr($codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } +} diff --git a/src/vendor/symfony/polyfill-php72/composer.json b/src/vendor/symfony/polyfill-php72/composer.json new file mode 100644 index 000000000..c96c84477 --- /dev/null +++ b/src/vendor/symfony/polyfill-php72/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/polyfill-php72", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/src/vendor/symfony/polyfill-php73/LICENSE b/src/vendor/symfony/polyfill-php73/LICENSE index 7536caeae..3f853aaf3 100644 --- a/src/vendor/symfony/polyfill-php73/LICENSE +++ b/src/vendor/symfony/polyfill-php73/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/polyfill-php73/README.md b/src/vendor/symfony/polyfill-php73/README.md index 032fafbda..b3ebbce51 100644 --- a/src/vendor/symfony/polyfill-php73/README.md +++ b/src/vendor/symfony/polyfill-php73/README.md @@ -10,7 +10,7 @@ This component provides functions added to PHP 7.3 core: - [`JsonException`](https://php.net/JsonException) More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/src/vendor/symfony/polyfill-php73/composer.json b/src/vendor/symfony/polyfill-php73/composer.json index 09d98cb87..a7fe47875 100644 --- a/src/vendor/symfony/polyfill-php73/composer.json +++ b/src/vendor/symfony/polyfill-php73/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, @@ -25,6 +25,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/src/vendor/symfony/polyfill-php80/LICENSE b/src/vendor/symfony/polyfill-php80/LICENSE index 0ed3a2465..5593b1d84 100644 --- a/src/vendor/symfony/polyfill-php80/LICENSE +++ b/src/vendor/symfony/polyfill-php80/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/polyfill-php80/PhpToken.php b/src/vendor/symfony/polyfill-php80/PhpToken.php index cd78c4ccc..fe6e69105 100644 --- a/src/vendor/symfony/polyfill-php80/PhpToken.php +++ b/src/vendor/symfony/polyfill-php80/PhpToken.php @@ -29,7 +29,7 @@ class PhpToken implements \Stringable public $text; /** - * @var -1|positive-int + * @var int */ public $line; @@ -38,9 +38,6 @@ class PhpToken implements \Stringable */ public $pos; - /** - * @param -1|positive-int $line - */ public function __construct(int $id, string $text, int $line = -1, int $position = -1) { $this->id = $id; @@ -83,7 +80,7 @@ class PhpToken implements \Stringable } /** - * @return list + * @return static[] */ public static function tokenize(string $code, int $flags = 0): array { diff --git a/src/vendor/symfony/polyfill-php80/README.md b/src/vendor/symfony/polyfill-php80/README.md index 3816c559d..10b8ee49a 100644 --- a/src/vendor/symfony/polyfill-php80/README.md +++ b/src/vendor/symfony/polyfill-php80/README.md @@ -3,13 +3,12 @@ Symfony Polyfill / Php80 This component provides features added to PHP 8.0 core: -- [`Stringable`](https://php.net/stringable) interface +- `Stringable` interface - [`fdiv`](https://php.net/fdiv) -- [`ValueError`](https://php.net/valueerror) class -- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class +- `ValueError` class +- `UnhandledMatchError` class - `FILTER_VALIDATE_BOOL` constant - [`get_debug_type`](https://php.net/get_debug_type) -- [`PhpToken`](https://php.net/phptoken) class - [`preg_last_error_msg`](https://php.net/preg_last_error_msg) - [`str_contains`](https://php.net/str_contains) - [`str_starts_with`](https://php.net/str_starts_with) diff --git a/src/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/src/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php index 2b955423f..7ea6d2772 100644 --- a/src/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php +++ b/src/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - #[Attribute(Attribute::TARGET_CLASS)] final class Attribute { diff --git a/src/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/src/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php index bd1212f6e..72f10812b 100644 --- a/src/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php +++ b/src/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -1,15 +1,6 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { +if (\PHP_VERSION_ID < 80000 && \extension_loaded('tokenizer')) { class PhpToken extends Symfony\Polyfill\Php80\PhpToken { } diff --git a/src/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/src/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php index 7c62d7508..77e037cb5 100644 --- a/src/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php +++ b/src/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { interface Stringable { diff --git a/src/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/src/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php index 01c6c6c8a..37937cbfa 100644 --- a/src/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +++ b/src/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { class UnhandledMatchError extends Error { diff --git a/src/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/src/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php index 783dbc28c..a3a9b88b0 100644 --- a/src/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php +++ b/src/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { class ValueError extends Error { diff --git a/src/vendor/symfony/polyfill-php80/composer.json b/src/vendor/symfony/polyfill-php80/composer.json index a503b039a..5fe679db3 100644 --- a/src/vendor/symfony/polyfill-php80/composer.json +++ b/src/vendor/symfony/polyfill-php80/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, @@ -29,6 +29,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/src/vendor/symfony/process/CHANGELOG.md b/src/vendor/symfony/process/CHANGELOG.md index 31b9ee6a2..69d4cbd77 100644 --- a/src/vendor/symfony/process/CHANGELOG.md +++ b/src/vendor/symfony/process/CHANGELOG.md @@ -1,26 +1,6 @@ CHANGELOG ========= -5.2.0 ------ - - * added `Process::setOptions()` to set `Process` specific options - * added option `create_new_console` to allow a subprocess to continue - to run after the main script exited, both on Linux and on Windows - -5.1.0 ------ - - * added `Process::getStartTime()` to retrieve the start time of the process as float - -5.0.0 ------ - - * removed `Process::inheritEnvironmentVariables()` - * removed `PhpProcess::setPhpBinary()` - * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell - * removed `Process::setCommandLine()` - 4.4.0 ----- diff --git a/src/vendor/symfony/process/ExecutableFinder.php b/src/vendor/symfony/process/ExecutableFinder.php index 89edd22fb..ff68ed331 100644 --- a/src/vendor/symfony/process/ExecutableFinder.php +++ b/src/vendor/symfony/process/ExecutableFinder.php @@ -19,15 +19,7 @@ namespace Symfony\Component\Process; */ class ExecutableFinder { - private const CMD_BUILTINS = [ - 'assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date', - 'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto', - 'help', 'if', 'label', 'md', 'mkdir', 'mklink', 'move', 'path', 'pause', - 'popd', 'prompt', 'pushd', 'rd', 'rem', 'ren', 'rename', 'rmdir', 'set', - 'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol', - ]; - - private $suffixes = []; + private $suffixes = ['.exe', '.bat', '.cmd', '.com']; /** * Replaces default suffixes of executable. @@ -39,8 +31,10 @@ class ExecutableFinder /** * Adds new possible suffix to check for executable. + * + * @param string $suffix */ - public function addSuffix(string $suffix) + public function addSuffix($suffix) { $this->suffixes[] = $suffix; } @@ -52,52 +46,43 @@ class ExecutableFinder * @param string|null $default The default to return if no executable is found * @param array $extraDirs Additional dirs to check into * - * @return string|null + * @return string|null The executable path or default value */ - public function find(string $name, ?string $default = null, array $extraDirs = []) + public function find($name, $default = null, array $extraDirs = []) { - // windows built-in commands that are present in cmd.exe should not be resolved using PATH as they do not exist as exes - if ('\\' === \DIRECTORY_SEPARATOR && \in_array(strtolower($name), self::CMD_BUILTINS, true)) { - return $name; + if (ini_get('open_basedir')) { + $searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); + $dirs = []; + foreach ($searchPath as $path) { + // Silencing against https://bugs.php.net/69240 + if (@is_dir($path)) { + $dirs[] = $path; + } else { + if (basename($path) == $name && @is_executable($path)) { + return $path; + } + } + } + } else { + $dirs = array_merge( + explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + $extraDirs + ); } - $dirs = array_merge( - explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), - $extraDirs - ); - - $suffixes = []; + $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); - $suffixes = $this->suffixes; - $suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']); + $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); } - $suffixes = '' !== pathinfo($name, PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']); foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { - if ('' === $dir) { - $dir = '.'; - } if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { return $file; } - - if (!@is_dir($dir) && basename($dir) === $name.$suffix && @is_executable($dir)) { - return $dir; - } } } - if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) { - return $default; - } - - $execResult = exec('command -v -- '.escapeshellarg($name)); - - if (($executablePath = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) && @is_executable($executablePath)) { - return $executablePath; - } - return $default; } } diff --git a/src/vendor/symfony/process/InputStream.php b/src/vendor/symfony/process/InputStream.php index 0c45b5245..4f8f71331 100644 --- a/src/vendor/symfony/process/InputStream.php +++ b/src/vendor/symfony/process/InputStream.php @@ -17,8 +17,6 @@ use Symfony\Component\Process\Exception\RuntimeException; * Provides a way to continuously write to the input of a Process until the InputStream is closed. * * @author Nicolas Grekas - * - * @implements \IteratorAggregate */ class InputStream implements \IteratorAggregate { @@ -30,7 +28,7 @@ class InputStream implements \IteratorAggregate /** * Sets a callback that is called when the write buffer becomes empty. */ - public function onEmpty(?callable $onEmpty = null) + public function onEmpty(callable $onEmpty = null) { $this->onEmpty = $onEmpty; } @@ -69,7 +67,7 @@ class InputStream implements \IteratorAggregate } /** - * @return \Traversable + * @return \Traversable */ #[\ReturnTypeWillChange] public function getIterator() diff --git a/src/vendor/symfony/process/LICENSE b/src/vendor/symfony/process/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/src/vendor/symfony/process/LICENSE +++ b/src/vendor/symfony/process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/process/PhpExecutableFinder.php b/src/vendor/symfony/process/PhpExecutableFinder.php index c3a9680d7..92e0262ad 100644 --- a/src/vendor/symfony/process/PhpExecutableFinder.php +++ b/src/vendor/symfony/process/PhpExecutableFinder.php @@ -29,13 +29,22 @@ class PhpExecutableFinder /** * Finds The PHP executable. * - * @return string|false + * @param bool $includeArgs Whether or not include command arguments + * + * @return string|false The PHP executable path or false if it cannot be found */ - public function find(bool $includeArgs = true) + public function find($includeArgs = true) { if ($php = getenv('PHP_BINARY')) { - if (!is_executable($php) && !$php = $this->executableFinder->find($php)) { - return false; + if (!is_executable($php)) { + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { + if (!is_executable($php)) { + return false; + } + } else { + return false; + } } if (@is_dir($php)) { @@ -49,7 +58,7 @@ class PhpExecutableFinder $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; // PHP_BINARY return the current sapi executable - if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], true)) { + if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) { return \PHP_BINARY.$args; } @@ -82,7 +91,7 @@ class PhpExecutableFinder /** * Finds the PHP executable arguments. * - * @return array + * @return array The PHP executable arguments */ public function findArguments() { diff --git a/src/vendor/symfony/process/PhpProcess.php b/src/vendor/symfony/process/PhpProcess.php index 3a1d147c8..dc064e0b8 100644 --- a/src/vendor/symfony/process/PhpProcess.php +++ b/src/vendor/symfony/process/PhpProcess.php @@ -32,7 +32,7 @@ class PhpProcess extends Process * @param int $timeout The timeout in seconds * @param array|null $php Path to the PHP binary to use with any additional arguments */ - public function __construct(string $script, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null) + public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) { if (null === $php) { $executableFinder = new PhpExecutableFinder(); @@ -53,15 +53,27 @@ class PhpProcess extends Process /** * {@inheritdoc} */ - public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); } + /** + * Sets the path to the PHP binary to use. + * + * @deprecated since Symfony 4.2, use the $php argument of the constructor instead. + */ + public function setPhpBinary($php) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the $php argument of the constructor instead.', __METHOD__), \E_USER_DEPRECATED); + + $this->setCommandLine($php); + } + /** * {@inheritdoc} */ - public function start(?callable $callback = null, array $env = []) + public function start(callable $callback = null, array $env = []) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); diff --git a/src/vendor/symfony/process/Pipes/AbstractPipes.php b/src/vendor/symfony/process/Pipes/AbstractPipes.php index 656dc0328..ab65866c2 100644 --- a/src/vendor/symfony/process/Pipes/AbstractPipes.php +++ b/src/vendor/symfony/process/Pipes/AbstractPipes.php @@ -104,8 +104,8 @@ abstract class AbstractPipes implements PipesInterface stream_set_blocking($input, 0); } elseif (!isset($this->inputBuffer[0])) { if (!\is_string($input)) { - if (!\is_scalar($input)) { - throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input))); + if (!is_scalar($input)) { + throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', \get_class($this->input), \gettype($input))); } $input = (string) $input; } diff --git a/src/vendor/symfony/process/Pipes/UnixPipes.php b/src/vendor/symfony/process/Pipes/UnixPipes.php index 5a0e9d47f..58a8da07c 100644 --- a/src/vendor/symfony/process/Pipes/UnixPipes.php +++ b/src/vendor/symfony/process/Pipes/UnixPipes.php @@ -35,7 +35,10 @@ class UnixPipes extends AbstractPipes parent::__construct($input); } - public function __sleep(): array + /** + * @return array + */ + public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } diff --git a/src/vendor/symfony/process/Pipes/WindowsPipes.php b/src/vendor/symfony/process/Pipes/WindowsPipes.php index 968dd0262..69768f3d8 100644 --- a/src/vendor/symfony/process/Pipes/WindowsPipes.php +++ b/src/vendor/symfony/process/Pipes/WindowsPipes.php @@ -88,7 +88,10 @@ class WindowsPipes extends AbstractPipes parent::__construct($input); } - public function __sleep(): array + /** + * @return array + */ + public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } @@ -149,7 +152,7 @@ class WindowsPipes extends AbstractPipes if ($w) { @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); } elseif ($this->fileHandles) { - usleep((int) (Process::TIMEOUT_PRECISION * 1E6)); + usleep(Process::TIMEOUT_PRECISION * 1E6); } } foreach ($this->fileHandles as $type => $fileHandle) { diff --git a/src/vendor/symfony/process/Process.php b/src/vendor/symfony/process/Process.php index 91f9e8fee..09cd9602a 100644 --- a/src/vendor/symfony/process/Process.php +++ b/src/vendor/symfony/process/Process.php @@ -27,8 +27,6 @@ use Symfony\Component\Process\Pipes\WindowsPipes; * * @author Fabien Potencier * @author Romain Neutron - * - * @implements \IteratorAggregate */ class Process implements \IteratorAggregate { @@ -73,14 +71,12 @@ class Process implements \IteratorAggregate private $incrementalErrorOutputOffset = 0; private $tty = false; private $pty; - private $options = ['suppress_errors' => true, 'bypass_shell' => true]; private $useFileHandles = false; /** @var PipesInterface */ private $processPipes; private $latestSignal; - private $cachedExitCode; private static $sigchild; @@ -141,12 +137,16 @@ class Process implements \IteratorAggregate * * @throws LogicException When proc_open is not installed */ - public function __construct(array $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public function __construct($command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { if (!\function_exists('proc_open')) { throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.'); } + if (!\is_array($command)) { + @trigger_error(sprintf('Passing a command as string when creating a "%s" instance is deprecated since Symfony 4.2, pass it as an array of its arguments instead, or use the "Process::fromShellCommandline()" constructor if you need features provided by the shell.', __CLASS__), \E_USER_DEPRECATED); + } + $this->commandline = $command; $this->cwd = $cwd; @@ -190,7 +190,7 @@ class Process implements \IteratorAggregate * * @throws LogicException When proc_open is not installed */ - public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { $process = new static([], $cwd, $env, $input, $timeout); $process->commandline = $command; @@ -213,11 +213,7 @@ class Process implements \IteratorAggregate public function __destruct() { - if ($this->options['create_new_console'] ?? false) { - $this->processPipes->close(); - } else { - $this->stop(0); - } + $this->stop(0); } public function __clone() @@ -248,7 +244,7 @@ class Process implements \IteratorAggregate * * @final */ - public function run(?callable $callback = null, array $env = []): int + public function run(callable $callback = null, array $env = []): int { $this->start($callback, $env); @@ -267,7 +263,7 @@ class Process implements \IteratorAggregate * * @final */ - public function mustRun(?callable $callback = null, array $env = []): self + public function mustRun(callable $callback = null, array $env = []): self { if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); @@ -295,7 +291,7 @@ class Process implements \IteratorAggregate * @throws RuntimeException When process is already running * @throws LogicException In case a callback is provided and output has been disabled */ - public function start(?callable $callback = null, array $env = []) + public function start(callable $callback = null, array $env = []) { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); @@ -324,7 +320,10 @@ class Process implements \IteratorAggregate $commandline = $this->replacePlaceholders($commandline, $env); } + $options = ['suppress_errors' => true]; + if ('\\' === \DIRECTORY_SEPARATOR) { + $options['bypass_shell'] = true; $commandline = $this->prepareWindowsCommandLine($commandline, $env); } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild @@ -332,7 +331,7 @@ class Process implements \IteratorAggregate // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; - $commandline .= 'pid=$!; echo $pid >&3; wait $pid 2>/dev/null; code=$?; echo $code >&3; exit $code'; + $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; // Workaround for the bug, when PTS functionality is enabled. // @see : https://bugs.php.net/69442 @@ -350,9 +349,9 @@ class Process implements \IteratorAggregate throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd)); } - $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); + $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $options); - if (!$this->process) { + if (!\is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; @@ -386,7 +385,7 @@ class Process implements \IteratorAggregate * * @final */ - public function restart(?callable $callback = null, array $env = []): self + public function restart(callable $callback = null, array $env = []): self { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); @@ -413,7 +412,7 @@ class Process implements \IteratorAggregate * @throws ProcessSignaledException When process stopped after receiving signal * @throws LogicException When process is not yet started */ - public function wait(?callable $callback = null) + public function wait(callable $callback = null) { $this->requireProcessIsStarted(__FUNCTION__); @@ -429,7 +428,7 @@ class Process implements \IteratorAggregate do { $this->checkTimeout(); - $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen()); + $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); } while ($running); @@ -512,7 +511,7 @@ class Process implements \IteratorAggregate * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed * @throws RuntimeException In case of failure */ - public function signal(int $signal) + public function signal($signal) { $this->doSignal($signal, true); @@ -533,7 +532,7 @@ class Process implements \IteratorAggregate throw new RuntimeException('Disabling output while the process is running is not possible.'); } if (null !== $this->idleTimeout) { - throw new LogicException('Output cannot be disabled while an idle timeout is set.'); + throw new LogicException('Output can not be disabled while an idle timeout is set.'); } $this->outputDisabled = true; @@ -572,7 +571,7 @@ class Process implements \IteratorAggregate /** * Returns the current output of the process (STDOUT). * - * @return string + * @return string The process output * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -594,7 +593,7 @@ class Process implements \IteratorAggregate * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * - * @return string + * @return string The process output since the last call * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -618,13 +617,13 @@ class Process implements \IteratorAggregate * * @param int $flags A bit field of Process::ITER_* flags * - * @return \Generator - * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started + * + * @return \Generator */ #[\ReturnTypeWillChange] - public function getIterator(int $flags = 0) + public function getIterator($flags = 0) { $this->readPipesForOutput(__FUNCTION__, false); @@ -688,7 +687,7 @@ class Process implements \IteratorAggregate /** * Returns the current error output of the process (STDERR). * - * @return string + * @return string The process error output * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -711,7 +710,7 @@ class Process implements \IteratorAggregate * whole error output, this one returns the new error output since the last * call. * - * @return string + * @return string The process error output since the last call * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -779,7 +778,7 @@ class Process implements \IteratorAggregate /** * Checks if the process ended successfully. * - * @return bool + * @return bool true if the process ended successfully, false otherwise */ public function isSuccessful() { @@ -817,7 +816,7 @@ class Process implements \IteratorAggregate $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.'); + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } return $this->processInformation['termsig']; @@ -858,7 +857,7 @@ class Process implements \IteratorAggregate /** * Checks if the process is currently running. * - * @return bool + * @return bool true if the process is currently running, false otherwise */ public function isRunning() { @@ -874,7 +873,7 @@ class Process implements \IteratorAggregate /** * Checks if the process has been started with no regard to the current state. * - * @return bool + * @return bool true if status is ready, false otherwise */ public function isStarted() { @@ -884,7 +883,7 @@ class Process implements \IteratorAggregate /** * Checks if the process is terminated. * - * @return bool + * @return bool true if process is terminated, false otherwise */ public function isTerminated() { @@ -898,7 +897,7 @@ class Process implements \IteratorAggregate * * The status is one of: ready, started, terminated. * - * @return string + * @return string The current process status */ public function getStatus() { @@ -911,11 +910,11 @@ class Process implements \IteratorAggregate * Stops the process. * * @param int|float $timeout The timeout in seconds - * @param int|null $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) + * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) * * @return int|null The exit-code of the process or null if it's not running */ - public function stop(float $timeout = 10, ?int $signal = null) + public function stop($timeout = 10, $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { @@ -983,7 +982,7 @@ class Process implements \IteratorAggregate /** * Gets the command line to be executed. * - * @return string + * @return string The command to execute */ public function getCommandLine() { @@ -991,9 +990,27 @@ class Process implements \IteratorAggregate } /** - * Gets the process timeout in seconds (max. runtime). + * Sets the command line to be executed. * - * @return float|null + * @param string|array $commandline The command to execute + * + * @return $this + * + * @deprecated since Symfony 4.2. + */ + public function setCommandLine($commandline) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); + + $this->commandline = $commandline; + + return $this; + } + + /** + * Gets the process timeout (max. runtime). + * + * @return float|null The timeout in seconds or null if it's disabled */ public function getTimeout() { @@ -1001,9 +1018,9 @@ class Process implements \IteratorAggregate } /** - * Gets the process idle timeout in seconds (max. time since last output). + * Gets the process idle timeout (max. time since last output). * - * @return float|null + * @return float|null The timeout in seconds or null if it's disabled */ public function getIdleTimeout() { @@ -1015,11 +1032,13 @@ class Process implements \IteratorAggregate * * To disable the timeout, set this value to null. * + * @param int|float|null $timeout The timeout in seconds + * * @return $this * * @throws InvalidArgumentException if the timeout is negative */ - public function setTimeout(?float $timeout) + public function setTimeout($timeout) { $this->timeout = $this->validateTimeout($timeout); @@ -1027,19 +1046,21 @@ class Process implements \IteratorAggregate } /** - * Sets the process idle timeout (max. time since last output) in seconds. + * Sets the process idle timeout (max. time since last output). * * To disable the timeout, set this value to null. * + * @param int|float|null $timeout The timeout in seconds + * * @return $this * * @throws LogicException if the output is disabled * @throws InvalidArgumentException if the timeout is negative */ - public function setIdleTimeout(?float $timeout) + public function setIdleTimeout($timeout) { if (null !== $timeout && $this->outputDisabled) { - throw new LogicException('Idle timeout cannot be set while the output is disabled.'); + throw new LogicException('Idle timeout can not be set while the output is disabled.'); } $this->idleTimeout = $this->validateTimeout($timeout); @@ -1050,11 +1071,13 @@ class Process implements \IteratorAggregate /** * Enables or disables the TTY mode. * + * @param bool $tty True to enabled and false to disable + * * @return $this * * @throws RuntimeException In case the TTY mode is not supported */ - public function setTty(bool $tty) + public function setTty($tty) { if ('\\' === \DIRECTORY_SEPARATOR && $tty) { throw new RuntimeException('TTY mode is not supported on Windows platform.'); @@ -1064,7 +1087,7 @@ class Process implements \IteratorAggregate throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); } - $this->tty = $tty; + $this->tty = (bool) $tty; return $this; } @@ -1072,7 +1095,7 @@ class Process implements \IteratorAggregate /** * Checks if the TTY mode is enabled. * - * @return bool + * @return bool true if the TTY mode is enabled, false otherwise */ public function isTty() { @@ -1082,11 +1105,13 @@ class Process implements \IteratorAggregate /** * Sets PTY mode. * + * @param bool $bool + * * @return $this */ - public function setPty(bool $bool) + public function setPty($bool) { - $this->pty = $bool; + $this->pty = (bool) $bool; return $this; } @@ -1104,7 +1129,7 @@ class Process implements \IteratorAggregate /** * Gets the working directory. * - * @return string|null + * @return string|null The current working directory or null on failure */ public function getWorkingDirectory() { @@ -1120,9 +1145,11 @@ class Process implements \IteratorAggregate /** * Sets the current working directory. * + * @param string $cwd The new working directory + * * @return $this */ - public function setWorkingDirectory(string $cwd) + public function setWorkingDirectory($cwd) { $this->cwd = $cwd; @@ -1132,7 +1159,7 @@ class Process implements \IteratorAggregate /** * Gets the environment variables. * - * @return array + * @return array The current environment variables */ public function getEnv() { @@ -1156,7 +1183,7 @@ class Process implements \IteratorAggregate /** * Gets the Process input. * - * @return resource|string|\Iterator|null + * @return resource|string|\Iterator|null The Process input */ public function getInput() { @@ -1177,7 +1204,7 @@ class Process implements \IteratorAggregate public function setInput($input) { if ($this->isRunning()) { - throw new LogicException('Input cannot be set while the process is running.'); + throw new LogicException('Input can not be set while the process is running.'); } $this->input = ProcessUtils::validateInput(__METHOD__, $input); @@ -1185,6 +1212,26 @@ class Process implements \IteratorAggregate return $this; } + /** + * Sets whether environment variables will be inherited or not. + * + * @param bool $inheritEnv + * + * @return $this + * + * @deprecated since Symfony 4.4, env variables are always inherited + */ + public function inheritEnvironmentVariables($inheritEnv = true) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.4, env variables are always inherited.', __METHOD__), \E_USER_DEPRECATED); + + if (!$inheritEnv) { + throw new InvalidArgumentException('Not inheriting environment variables is not supported.'); + } + + return $this; + } + /** * Performs a check between the timeout definition and the time the process started. * @@ -1212,44 +1259,6 @@ class Process implements \IteratorAggregate } } - /** - * @throws LogicException in case process is not started - */ - public function getStartTime(): float - { - if (!$this->isStarted()) { - throw new LogicException('Start time is only available after process start.'); - } - - return $this->starttime; - } - - /** - * Defines options to pass to the underlying proc_open(). - * - * @see https://php.net/proc_open for the options supported by PHP. - * - * Enabling the "create_new_console" option allows a subprocess to continue - * to run after the main process exited, on both Windows and *nix - */ - public function setOptions(array $options) - { - if ($this->isRunning()) { - throw new RuntimeException('Setting options while the process is running is not possible.'); - } - - $defaultOptions = $this->options; - $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console']; - - foreach ($options as $key => $value) { - if (!\in_array($key, $existingOptions)) { - $this->options = $defaultOptions; - throw new LogicException(sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions))); - } - $this->options[$key] = $value; - } - } - /** * Returns whether TTY is supported on the current operating system. */ @@ -1309,9 +1318,9 @@ class Process implements \IteratorAggregate * * @param callable|null $callback The user defined PHP callback * - * @return \Closure + * @return \Closure A PHP closure */ - protected function buildCallback(?callable $callback = null) + protected function buildCallback(callable $callback = null) { if ($this->outputDisabled) { return function ($type, $data) use ($callback): bool { @@ -1337,7 +1346,7 @@ class Process implements \IteratorAggregate * * @param bool $blocking Whether to use a blocking read call */ - protected function updateStatus(bool $blocking) + protected function updateStatus($blocking) { if (self::STATUS_STARTED !== $this->status) { return; @@ -1346,19 +1355,6 @@ class Process implements \IteratorAggregate $this->processInformation = proc_get_status($this->process); $running = $this->processInformation['running']; - // In PHP < 8.3, "proc_get_status" only returns the correct exit status on the first call. - // Subsequent calls return -1 as the process is discarded. This workaround caches the first - // retrieved exit status for consistent results in later calls, mimicking PHP 8.3 behavior. - if (\PHP_VERSION_ID < 80300) { - if (!isset($this->cachedExitCode) && !$running && -1 !== $this->processInformation['exitcode']) { - $this->cachedExitCode = $this->processInformation['exitcode']; - } - - if (isset($this->cachedExitCode) && !$running && -1 === $this->processInformation['exitcode']) { - $this->processInformation['exitcode'] = $this->cachedExitCode; - } - } - $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); if ($this->fallbackStatus && $this->isSigchildEnabled()) { @@ -1456,9 +1452,8 @@ class Process implements \IteratorAggregate private function close(): int { $this->processPipes->close(); - if ($this->process) { + if (\is_resource($this->process)) { proc_close($this->process); - $this->process = null; } $this->exitcode = $this->processInformation['exitcode']; $this->status = self::STATUS_TERMINATED; @@ -1514,7 +1509,7 @@ class Process implements \IteratorAggregate { if (null === $pid = $this->getPid()) { if ($throwException) { - throw new LogicException('Cannot send signal on a non running process.'); + throw new LogicException('Can not send signal on a non running process.'); } return false; @@ -1592,14 +1587,7 @@ class Process implements \IteratorAggregate $cmd ); - static $comSpec; - - if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) { - // Escape according to CommandLineToArgvW rules - $comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec) .'"'; - } - - $cmd = ($comSpec ?? 'cmd').' /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; + $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $cmd .= ' '.$offset.'>"'.$filename.'"'; } @@ -1645,7 +1633,7 @@ class Process implements \IteratorAggregate if (str_contains($argument, "\0")) { $argument = str_replace("\0", '?', $argument); } - if (!preg_match('/[()%!^"<>&|\s]/', $argument)) { + if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { return $argument; } $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); diff --git a/src/vendor/symfony/process/ProcessUtils.php b/src/vendor/symfony/process/ProcessUtils.php index 2a7aff71b..eb39a4a9e 100644 --- a/src/vendor/symfony/process/ProcessUtils.php +++ b/src/vendor/symfony/process/ProcessUtils.php @@ -35,11 +35,11 @@ class ProcessUtils * @param string $caller The name of method call that validates the input * @param mixed $input The input to validate * - * @return mixed + * @return mixed The validated input * * @throws InvalidArgumentException In case the input is not valid */ - public static function validateInput(string $caller, $input) + public static function validateInput($caller, $input) { if (null !== $input) { if (\is_resource($input)) { @@ -48,7 +48,7 @@ class ProcessUtils if (\is_string($input)) { return $input; } - if (\is_scalar($input)) { + if (is_scalar($input)) { return (string) $input; } if ($input instanceof Process) { diff --git a/src/vendor/symfony/process/README.md b/src/vendor/symfony/process/README.md index 8777de4a6..afce5e45e 100644 --- a/src/vendor/symfony/process/README.md +++ b/src/vendor/symfony/process/README.md @@ -3,17 +3,6 @@ Process Component The Process component executes commands in sub-processes. -Sponsor -------- - -The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. - -As the creator of Symfony, SensioLabs supports companies using Symfony, with an -offering encompassing consultancy, expertise, services, training, and technical -assistance to ensure the success of web application development projects. - -Help Symfony by [sponsoring][3] its development! - Resources --------- @@ -22,7 +11,3 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) - -[1]: https://symfony.com/backers -[2]: https://sensiolabs.com -[3]: https://symfony.com/sponsor diff --git a/src/vendor/symfony/process/composer.json b/src/vendor/symfony/process/composer.json index 1669eba57..c0f7599f2 100644 --- a/src/vendor/symfony/process/composer.json +++ b/src/vendor/symfony/process/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2.5", + "php": ">=7.1.3", "symfony/polyfill-php80": "^1.16" }, "autoload": { diff --git a/src/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml b/src/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml new file mode 100644 index 000000000..4c0e8aeef --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + pull_request: + push: + +jobs: + test: + name: 'Test ${{ matrix.deps }} on PHP ${{ matrix.php }}' + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['7.1.3', '7.2', '7.3', '7.4', '8.0', '8.1'] + include: + - php: '7.4' + deps: lowest + deprecations: max[self]=0 + - php: '8.0' + deps: highest + deprecations: max[indirect]=5 + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '${{ matrix.php }}' + coverage: none + + - name: Configure composer + if: "${{ matrix.deps == 'highest' }}" + run: composer config minimum-stability dev + + - name: Composer install + uses: ramsey/composer-install@v1 + with: + dependency-versions: '${{ matrix.deps }}' + + - name: Install PHPUnit + run: vendor/bin/simple-phpunit install + + - name: Run tests + run: vendor/bin/simple-phpunit + env: + SYMFONY_DEPRECATIONS_HELPER: '${{ matrix.deprecations }}' diff --git a/src/vendor/symfony/psr-http-message-bridge/.php_cs.dist b/src/vendor/symfony/psr-http-message-bridge/.php_cs.dist new file mode 100644 index 000000000..d741d39f5 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/.php_cs.dist @@ -0,0 +1,24 @@ +setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + '@PHPUnit48Migration:risky' => true, + 'php_unit_no_expectation_annotation' => false, // part of `PHPUnitXYMigration:risky` ruleset, to be enabled when PHPUnit 4.x support will be dropped, as we don't want to rewrite exceptions handling twice + 'array_syntax' => ['syntax' => 'short'], + 'fopen_flags' => false, + 'ordered_imports' => true, + 'protected_to_private' => false, + // Part of @Symfony:risky in PHP-CS-Fixer 2.13.0. To be removed from the config file once upgrading + 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced'], + // Part of future @Symfony ruleset in PHP-CS-Fixer To be removed from the config file once upgrading + 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], + ]) + ->setRiskyAllowed(true) + ->setFinder( + PhpCsFixer\Finder::create() + ->in(__DIR__) + ->name('*.php') + ) +; diff --git a/src/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php b/src/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php index 61cd8c5c5..29dc7dc98 100644 --- a/src/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php +++ b/src/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php @@ -17,7 +17,6 @@ use Psr\Http\Message\ServerRequestInterface; use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\Controller\ValueResolverInterface as BaseValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** @@ -26,7 +25,7 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; * @author Iltar van der Berg * @author Alexander M. Turek */ -final class PsrServerRequestResolver implements ArgumentValueResolverInterface, ValueResolverInterface +final class PsrServerRequestResolver implements ArgumentValueResolverInterface { private const SUPPORTED_TYPES = [ ServerRequestInterface::class => true, @@ -46,10 +45,6 @@ final class PsrServerRequestResolver implements ArgumentValueResolverInterface, */ public function supports(Request $request, ArgumentMetadata $argument): bool { - if ($this instanceof BaseValueResolverInterface) { - trigger_deprecation('symfony/psr-http-message-bridge', '2.3', 'Method "%s" is deprecated, call "resolve()" without calling "supports()" first.', __METHOD__); - } - return self::SUPPORTED_TYPES[$argument->getType()] ?? false; } @@ -58,10 +53,6 @@ final class PsrServerRequestResolver implements ArgumentValueResolverInterface, */ public function resolve(Request $request, ArgumentMetadata $argument): \Traversable { - if (!isset(self::SUPPORTED_TYPES[$argument->getType()])) { - return; - } - yield $this->httpMessageFactory->createRequest($request); } } diff --git a/src/vendor/symfony/psr-http-message-bridge/CHANGELOG.md b/src/vendor/symfony/psr-http-message-bridge/CHANGELOG.md index f32c06f2e..c17d8f342 100644 --- a/src/vendor/symfony/psr-http-message-bridge/CHANGELOG.md +++ b/src/vendor/symfony/psr-http-message-bridge/CHANGELOG.md @@ -1,26 +1,6 @@ CHANGELOG ========= -# 2.3.1 (2023-07-26) - -* Don't rely on `Request::getPayload()` to populate the parsed body - -# 2.3.0 (2023-07-25) - -* Leverage `Request::getPayload()` to populate the parsed body of PSR-7 requests -* Implement `ValueResolverInterface` introduced with Symfony 6.2 - -# 2.2.0 (2023-04-21) - -* Drop support for Symfony 4 -* Bump minimum version of PHP to 7.2 -* Support version 2 of the psr/http-message contracts - -# 2.1.3 (2022-09-05) - -* Ignore invalid HTTP headers when creating PSR7 objects -* Fix for wrong type passed to `moveTo()` - # 2.1.2 (2021-11-05) * Allow Symfony 6 diff --git a/src/vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php b/src/vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php index a69e8ffee..457e3468d 100644 --- a/src/vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php +++ b/src/vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php @@ -41,8 +41,6 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface /** * {@inheritdoc} - * - * @return Request */ public function createRequest(ServerRequestInterface $psrRequest, bool $streamed = false) { @@ -123,8 +121,6 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface /** * {@inheritdoc} - * - * @return Response */ public function createResponse(ResponseInterface $psrResponse, bool $streamed = false) { @@ -221,13 +217,13 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface return new Cookie( $cookieName, $cookieValue, - $cookieExpire ?? 0, - $cookiePath ?? '/', - $cookieDomain ?? null, + isset($cookieExpire) ? $cookieExpire : 0, + isset($cookiePath) ? $cookiePath : '/', + isset($cookieDomain) ? $cookieDomain : null, isset($cookieSecure), isset($cookieHttpOnly), true, - $samesite ?? null + isset($samesite) ? $samesite : null ); } diff --git a/src/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php b/src/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php index 09c4360dd..d19baa1ab 100644 --- a/src/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php +++ b/src/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php @@ -12,9 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestFactoryInterface; -use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\UploadedFileFactoryInterface; use Psr\Http\Message\UploadedFileInterface; @@ -29,7 +27,6 @@ use Symfony\Component\HttpFoundation\StreamedResponse; * Builds Psr\HttpMessage instances using a PSR-17 implementation. * * @author Antonio J. García Lagar - * @author Aurélien Pillevesse */ class PsrHttpFactory implements HttpMessageFactoryInterface { @@ -48,8 +45,6 @@ class PsrHttpFactory implements HttpMessageFactoryInterface /** * {@inheritdoc} - * - * @return ServerRequestInterface */ public function createRequest(Request $symfonyRequest) { @@ -63,37 +58,17 @@ class PsrHttpFactory implements HttpMessageFactoryInterface ); foreach ($symfonyRequest->headers->all() as $name => $value) { - try { - $request = $request->withHeader($name, $value); - } catch (\InvalidArgumentException $e) { - // ignore invalid header - } + $request = $request->withHeader($name, $value); } $body = $this->streamFactory->createStreamFromResource($symfonyRequest->getContent(true)); - if (method_exists(Request::class, 'getContentTypeFormat')) { - $format = $symfonyRequest->getContentTypeFormat(); - } else { - $format = $symfonyRequest->getContentType(); - } - - if ('json' === $format) { - $parsedBody = json_decode($symfonyRequest->getContent(), true, 512, \JSON_BIGINT_AS_STRING); - - if (!\is_array($parsedBody)) { - $parsedBody = null; - } - } else { - $parsedBody = $symfonyRequest->request->all(); - } - $request = $request ->withBody($body) ->withUploadedFiles($this->getFiles($symfonyRequest->files->all())) ->withCookieParams($symfonyRequest->cookies->all()) ->withQueryParams($symfonyRequest->query->all()) - ->withParsedBody($parsedBody) + ->withParsedBody($symfonyRequest->request->all()) ; foreach ($symfonyRequest->attributes->all() as $key => $value) { @@ -105,8 +80,10 @@ class PsrHttpFactory implements HttpMessageFactoryInterface /** * Converts Symfony uploaded files array to the PSR one. + * + * @return array */ - private function getFiles(array $uploadedFiles): array + private function getFiles(array $uploadedFiles) { $files = []; @@ -127,8 +104,10 @@ class PsrHttpFactory implements HttpMessageFactoryInterface /** * Creates a PSR-7 UploadedFile instance from a Symfony one. + * + * @return UploadedFileInterface */ - private function createUploadedFile(UploadedFile $symfonyUploadedFile): UploadedFileInterface + private function createUploadedFile(UploadedFile $symfonyUploadedFile) { return $this->uploadedFileFactory->createUploadedFile( $this->streamFactory->createStreamFromFile( @@ -143,8 +122,6 @@ class PsrHttpFactory implements HttpMessageFactoryInterface /** * {@inheritdoc} - * - * @return ResponseInterface */ public function createResponse(Response $symfonyResponse) { @@ -161,7 +138,7 @@ class PsrHttpFactory implements HttpMessageFactoryInterface $stream->write($buffer); return ''; - }, 1); + }); $symfonyResponse->sendContent(); ob_end_clean(); @@ -183,11 +160,7 @@ class PsrHttpFactory implements HttpMessageFactoryInterface } foreach ($headers as $name => $value) { - try { - $response = $response->withHeader($name, $value); - } catch (\InvalidArgumentException $e) { - // ignore invalid header - } + $response = $response->withHeader($name, $value); } $protocolVersion = $symfonyResponse->getProtocolVersion(); diff --git a/src/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php b/src/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php index 4d38a1f7c..53aa37a62 100644 --- a/src/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php +++ b/src/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php @@ -52,7 +52,7 @@ class UploadedFile extends BaseUploadedFile /** * {@inheritdoc} */ - public function move(string $directory, string $name = null): File + public function move($directory, $name = null): File { if (!$this->isValid() || $this->test) { return parent::move($directory, $name); @@ -61,7 +61,7 @@ class UploadedFile extends BaseUploadedFile $target = $this->getTargetFile($directory, $name); try { - $this->psrUploadedFile->moveTo((string) $target); + $this->psrUploadedFile->moveTo($target); } catch (\RuntimeException $e) { throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, $e->getMessage()), 0, $e); } diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php new file mode 100644 index 000000000..662b18691 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\ArgumentValueResolver; + +use PHPUnit\Framework\TestCase; +use Psr\Http\Message\MessageInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; +use Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver\PsrServerRequestResolver; +use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +/** + * @author Alexander M. Turek + */ +final class PsrServerRequestResolverTest extends TestCase +{ + public function testServerRequest() + { + $symfonyRequest = $this->createMock(Request::class); + $psrRequest = $this->createMock(ServerRequestInterface::class); + + $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest); + + self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (ServerRequestInterface $serverRequest): void {})); + } + + public function testRequest() + { + $symfonyRequest = $this->createMock(Request::class); + $psrRequest = $this->createMock(ServerRequestInterface::class); + + $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest); + + self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (RequestInterface $request): void {})); + } + + public function testMessage() + { + $symfonyRequest = $this->createMock(Request::class); + $psrRequest = $this->createMock(ServerRequestInterface::class); + + $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest); + + self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (MessageInterface $request): void {})); + } + + private function bootstrapResolver(Request $symfonyRequest, ServerRequestInterface $psrRequest): ArgumentResolver + { + $messageFactory = $this->createMock(HttpMessageFactoryInterface::class); + $messageFactory->expects(self::once()) + ->method('createRequest') + ->with(self::identicalTo($symfonyRequest)) + ->willReturn($psrRequest); + + return new ArgumentResolver(null, [new PsrServerRequestResolver($messageFactory)]); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.php new file mode 100644 index 000000000..9a94b20ac --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PsrHttpMessage\EventListener\PsrResponseListener; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\ViewEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * @author Kévin Dunglas + */ +class PsrResponseListenerTest extends TestCase +{ + public function testConvertsControllerResult() + { + $listener = new PsrResponseListener(); + $event = $this->createEventMock(new Response()); + $listener->onKernelView($event); + + self::assertTrue($event->hasResponse()); + } + + public function testDoesNotConvertControllerResult() + { + $listener = new PsrResponseListener(); + $event = $this->createEventMock([]); + + $listener->onKernelView($event); + self::assertFalse($event->hasResponse()); + + $event = $this->createEventMock(null); + + $listener->onKernelView($event); + self::assertFalse($event->hasResponse()); + } + + private function createEventMock($controllerResult): ViewEvent + { + return new ViewEvent($this->createMock(HttpKernelInterface::class), new Request(), HttpKernelInterface::MASTER_REQUEST, $controllerResult); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/AbstractHttpMessageFactoryTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/AbstractHttpMessageFactoryTest.php new file mode 100644 index 000000000..82d3fc789 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/AbstractHttpMessageFactoryTest.php @@ -0,0 +1,234 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; +use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; + +/** + * @author Kévin Dunglas + * @author Antonio J. García Lagar + */ +abstract class AbstractHttpMessageFactoryTest extends TestCase +{ + private $factory; + private $tmpDir; + + abstract protected function buildHttpMessageFactory(): HttpMessageFactoryInterface; + + protected function setUp(): void + { + $this->factory = $this->buildHttpMessageFactory(); + $this->tmpDir = sys_get_temp_dir(); + } + + public function testCreateRequest() + { + $stdClass = new \stdClass(); + $request = new Request( + [ + 'bar' => ['baz' => '42'], + 'foo' => '1', + ], + [ + 'twitter' => [ + '@dunglas' => 'Kévin Dunglas', + '@coopTilleuls' => 'Les-Tilleuls.coop', + ], + 'baz' => '2', + ], + [ + 'a1' => $stdClass, + 'a2' => ['foo' => 'bar'], + ], + [ + 'c1' => 'foo', + 'c2' => ['c3' => 'bar'], + ], + [ + 'f1' => $this->createUploadedFile('F1', 'f1.txt', 'text/plain', \UPLOAD_ERR_OK), + 'foo' => ['f2' => $this->createUploadedFile('F2', 'f2.txt', 'text/plain', \UPLOAD_ERR_OK)], + ], + [ + 'REQUEST_METHOD' => 'POST', + 'HTTP_HOST' => 'dunglas.fr', + 'HTTP_X_SYMFONY' => '2.8', + 'REQUEST_URI' => '/testCreateRequest?bar[baz]=42&foo=1', + 'QUERY_STRING' => 'bar[baz]=42&foo=1', + ], + 'Content' + ); + + $psrRequest = $this->factory->createRequest($request); + + $this->assertEquals('Content', $psrRequest->getBody()->__toString()); + + $queryParams = $psrRequest->getQueryParams(); + $this->assertEquals('1', $queryParams['foo']); + $this->assertEquals('42', $queryParams['bar']['baz']); + + $requestTarget = $psrRequest->getRequestTarget(); + $this->assertEquals('/testCreateRequest?bar[baz]=42&foo=1', urldecode($requestTarget)); + + $parsedBody = $psrRequest->getParsedBody(); + $this->assertEquals('Kévin Dunglas', $parsedBody['twitter']['@dunglas']); + $this->assertEquals('Les-Tilleuls.coop', $parsedBody['twitter']['@coopTilleuls']); + $this->assertEquals('2', $parsedBody['baz']); + + $attributes = $psrRequest->getAttributes(); + $this->assertEquals($stdClass, $attributes['a1']); + $this->assertEquals('bar', $attributes['a2']['foo']); + + $cookies = $psrRequest->getCookieParams(); + $this->assertEquals('foo', $cookies['c1']); + $this->assertEquals('bar', $cookies['c2']['c3']); + + $uploadedFiles = $psrRequest->getUploadedFiles(); + $this->assertEquals('F1', $uploadedFiles['f1']->getStream()->__toString()); + $this->assertEquals('f1.txt', $uploadedFiles['f1']->getClientFilename()); + $this->assertEquals('text/plain', $uploadedFiles['f1']->getClientMediaType()); + $this->assertEquals(\UPLOAD_ERR_OK, $uploadedFiles['f1']->getError()); + + $this->assertEquals('F2', $uploadedFiles['foo']['f2']->getStream()->__toString()); + $this->assertEquals('f2.txt', $uploadedFiles['foo']['f2']->getClientFilename()); + $this->assertEquals('text/plain', $uploadedFiles['foo']['f2']->getClientMediaType()); + $this->assertEquals(\UPLOAD_ERR_OK, $uploadedFiles['foo']['f2']->getError()); + + $serverParams = $psrRequest->getServerParams(); + $this->assertEquals('POST', $serverParams['REQUEST_METHOD']); + $this->assertEquals('2.8', $serverParams['HTTP_X_SYMFONY']); + $this->assertEquals('POST', $psrRequest->getMethod()); + $this->assertEquals(['2.8'], $psrRequest->getHeader('X-Symfony')); + } + + public function testGetContentCanBeCalledAfterRequestCreation() + { + $header = ['HTTP_HOST' => 'dunglas.fr']; + $request = new Request([], [], [], [], [], $header, 'Content'); + + $psrRequest = $this->factory->createRequest($request); + + $this->assertEquals('Content', $psrRequest->getBody()->__toString()); + $this->assertEquals('Content', $request->getContent()); + } + + private function createUploadedFile($content, $originalName, $mimeType, $error) + { + $path = tempnam($this->tmpDir, uniqid()); + file_put_contents($path, $content); + + return new UploadedFile($path, $originalName, $mimeType, $error, true); + } + + public function testCreateResponse() + { + $response = new Response( + 'Response content.', + 202, + ['X-Symfony' => ['3.4']] + ); + $response->headers->setCookie(new Cookie('city', 'Lille', new \DateTime('Wed, 13 Jan 2021 22:23:01 GMT'), '/', null, false, true, false, 'lax')); + + $psrResponse = $this->factory->createResponse($response); + $this->assertEquals('Response content.', $psrResponse->getBody()->__toString()); + $this->assertEquals(202, $psrResponse->getStatusCode()); + $this->assertEquals(['3.4'], $psrResponse->getHeader('X-Symfony')); + + $cookieHeader = $psrResponse->getHeader('Set-Cookie'); + $this->assertIsArray($cookieHeader); + $this->assertCount(1, $cookieHeader); + $this->assertMatchesRegularExpression('{city=Lille; expires=Wed, 13-Jan-2021 22:23:01 GMT;( max-age=\d+;)? path=/; httponly}i', $cookieHeader[0]); + } + + public function testCreateResponseFromStreamed() + { + $response = new StreamedResponse(function () { + echo "Line 1\n"; + flush(); + + echo "Line 2\n"; + flush(); + }); + + $psrResponse = $this->factory->createResponse($response); + + $this->assertEquals("Line 1\nLine 2\n", $psrResponse->getBody()->__toString()); + } + + public function testCreateResponseFromBinaryFile() + { + $path = tempnam($this->tmpDir, uniqid()); + file_put_contents($path, 'Binary'); + + $response = new BinaryFileResponse($path); + + $psrResponse = $this->factory->createResponse($response); + + $this->assertEquals('Binary', $psrResponse->getBody()->__toString()); + } + + public function testCreateResponseFromBinaryFileWithRange() + { + $path = tempnam($this->tmpDir, uniqid()); + file_put_contents($path, 'Binary'); + + $request = new Request(); + $request->headers->set('Range', 'bytes=1-4'); + + $response = new BinaryFileResponse($path, 200, ['Content-Type' => 'plain/text']); + $response->prepare($request); + + $psrResponse = $this->factory->createResponse($response); + + $this->assertEquals('inar', $psrResponse->getBody()->__toString()); + $this->assertSame('bytes 1-4/6', $psrResponse->getHeaderLine('Content-Range')); + } + + public function testUploadErrNoFile() + { + $file = new UploadedFile('', '', null, \UPLOAD_ERR_NO_FILE, true); + + $this->assertEquals(0, $file->getSize()); + $this->assertEquals(\UPLOAD_ERR_NO_FILE, $file->getError()); + $this->assertFalse($file->getSize(), 'SplFile::getSize() returns false on error'); + + $request = new Request( + [], + [], + [], + [], + [ + 'f1' => $file, + 'f2' => ['name' => null, 'type' => null, 'tmp_name' => null, 'error' => \UPLOAD_ERR_NO_FILE, 'size' => 0], + ], + [ + 'REQUEST_METHOD' => 'POST', + 'HTTP_HOST' => 'dunglas.fr', + 'HTTP_X_SYMFONY' => '2.8', + ], + 'Content' + ); + + $psrRequest = $this->factory->createRequest($request); + + $uploadedFiles = $psrRequest->getUploadedFiles(); + + $this->assertEquals(\UPLOAD_ERR_NO_FILE, $uploadedFiles['f1']->getError()); + $this->assertEquals(\UPLOAD_ERR_NO_FILE, $uploadedFiles['f2']->getError()); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/HttpFoundationFactoryTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/HttpFoundationFactoryTest.php new file mode 100644 index 000000000..3a00e2fa7 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/HttpFoundationFactoryTest.php @@ -0,0 +1,272 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; + +use PHPUnit\Framework\TestCase; +use Psr\Http\Message\UploadedFileInterface; +use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\ServerRequest; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Stream; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\UploadedFile; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Uri; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\UploadedFile as HttpFoundationUploadedFile; + +/** + * @author Kévin Dunglas + */ +class HttpFoundationFactoryTest extends TestCase +{ + /** @var HttpFoundationFactory */ + private $factory; + + /** @var string */ + private $tmpDir; + + protected function setUp(): void + { + $this->factory = new HttpFoundationFactory(); + $this->tmpDir = sys_get_temp_dir(); + } + + public function testCreateRequest() + { + $stdClass = new \stdClass(); + $serverRequest = new ServerRequest( + '1.1', + [ + 'X-Dunglas-API-Platform' => '1.0', + 'X-data' => ['a', 'b'], + ], + new Stream('The body'), + '/about/kevin', + 'GET', + 'http://les-tilleuls.coop/about/kevin', + ['country' => 'France'], + ['city' => 'Lille'], + ['url' => 'http://les-tilleuls.coop'], + [ + 'doc1' => $this->createUploadedFile('Doc 1', \UPLOAD_ERR_OK, 'doc1.txt', 'text/plain'), + 'nested' => [ + 'docs' => [ + $this->createUploadedFile('Doc 2', \UPLOAD_ERR_OK, 'doc2.txt', 'text/plain'), + $this->createUploadedFile('Doc 3', \UPLOAD_ERR_OK, 'doc3.txt', 'text/plain'), + ], + ], + ], + ['url' => 'http://dunglas.fr'], + ['custom' => $stdClass] + ); + + $symfonyRequest = $this->factory->createRequest($serverRequest); + $files = $symfonyRequest->files->all(); + + $this->assertEquals('http://les-tilleuls.coop', $symfonyRequest->query->get('url')); + $this->assertEquals('doc1.txt', $files['doc1']->getClientOriginalName()); + $this->assertEquals('doc2.txt', $files['nested']['docs'][0]->getClientOriginalName()); + $this->assertEquals('doc3.txt', $files['nested']['docs'][1]->getClientOriginalName()); + $this->assertEquals('http://dunglas.fr', $symfonyRequest->request->get('url')); + $this->assertEquals($stdClass, $symfonyRequest->attributes->get('custom')); + $this->assertEquals('Lille', $symfonyRequest->cookies->get('city')); + $this->assertEquals('France', $symfonyRequest->server->get('country')); + $this->assertEquals('The body', $symfonyRequest->getContent()); + $this->assertEquals('1.0', $symfonyRequest->headers->get('X-Dunglas-API-Platform')); + $this->assertEquals(['a', 'b'], $symfonyRequest->headers->all('X-data')); + } + + public function testCreateRequestWithStreamedBody() + { + $serverRequest = new ServerRequest( + '1.1', + [], + new Stream('The body'), + '/', + 'GET', + null, + [], + [], + [], + [], + null, + [] + ); + + $symfonyRequest = $this->factory->createRequest($serverRequest, true); + $this->assertEquals('The body', $symfonyRequest->getContent()); + } + + public function testCreateRequestWithNullParsedBody() + { + $serverRequest = new ServerRequest( + '1.1', + [], + new Stream(), + '/', + 'GET', + null, + [], + [], + [], + [], + null, + [] + ); + + $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); + } + + public function testCreateRequestWithObjectParsedBody() + { + $serverRequest = new ServerRequest( + '1.1', + [], + new Stream(), + '/', + 'GET', + null, + [], + [], + [], + [], + new \stdClass(), + [] + ); + + $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); + } + + public function testCreateRequestWithUri() + { + $serverRequest = new ServerRequest( + '1.1', + [], + new Stream(), + '/', + 'GET', + new Uri('http://les-tilleuls.coop/about/kevin'), + [], + [], + [], + [], + null, + [] + ); + + $this->assertEquals('/about/kevin', $this->factory->createRequest($serverRequest)->getPathInfo()); + } + + public function testCreateUploadedFile() + { + $uploadedFile = $this->createUploadedFile('An uploaded file.', \UPLOAD_ERR_OK, 'myfile.txt', 'text/plain'); + $symfonyUploadedFile = $this->callCreateUploadedFile($uploadedFile); + $size = $symfonyUploadedFile->getSize(); + + $uniqid = uniqid(); + $symfonyUploadedFile->move($this->tmpDir, $uniqid); + + $this->assertEquals($uploadedFile->getSize(), $size); + $this->assertEquals(\UPLOAD_ERR_OK, $symfonyUploadedFile->getError()); + $this->assertEquals('myfile.txt', $symfonyUploadedFile->getClientOriginalName()); + $this->assertEquals('txt', $symfonyUploadedFile->getClientOriginalExtension()); + $this->assertEquals('text/plain', $symfonyUploadedFile->getClientMimeType()); + $this->assertEquals('An uploaded file.', file_get_contents($this->tmpDir.'/'.$uniqid)); + } + + public function testCreateUploadedFileWithError() + { + $this->expectException(FileException::class); + $this->expectExceptionMessage('The file "e" could not be written on disk.'); + + $uploadedFile = $this->createUploadedFile('Error.', \UPLOAD_ERR_CANT_WRITE, 'e', 'text/plain'); + $symfonyUploadedFile = $this->callCreateUploadedFile($uploadedFile); + + $this->assertEquals(\UPLOAD_ERR_CANT_WRITE, $symfonyUploadedFile->getError()); + + $symfonyUploadedFile->move($this->tmpDir, 'shouldFail.txt'); + } + + private function createUploadedFile($content, $error, $clientFileName, $clientMediaType): UploadedFile + { + $filePath = tempnam($this->tmpDir, uniqid()); + file_put_contents($filePath, $content); + + return new UploadedFile($filePath, filesize($filePath), $error, $clientFileName, $clientMediaType); + } + + private function callCreateUploadedFile(UploadedFileInterface $uploadedFile): HttpFoundationUploadedFile + { + $reflection = new \ReflectionClass($this->factory); + $createUploadedFile = $reflection->getMethod('createUploadedFile'); + $createUploadedFile->setAccessible(true); + + return $createUploadedFile->invokeArgs($this->factory, [$uploadedFile]); + } + + public function testCreateResponse() + { + $response = new Response( + '1.0', + [ + 'X-Symfony' => ['2.8'], + 'Set-Cookie' => [ + 'theme=light', + 'test', + 'ABC=AeD; Domain=dunglas.fr; Path=/kevin; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly; SameSite=Strict', + ], + ], + new Stream('The response body'), + 200 + ); + + $symfonyResponse = $this->factory->createResponse($response); + + $this->assertEquals('1.0', $symfonyResponse->getProtocolVersion()); + $this->assertEquals('2.8', $symfonyResponse->headers->get('X-Symfony')); + + $cookies = $symfonyResponse->headers->getCookies(); + $this->assertEquals('theme', $cookies[0]->getName()); + $this->assertEquals('light', $cookies[0]->getValue()); + $this->assertEquals(0, $cookies[0]->getExpiresTime()); + $this->assertNull($cookies[0]->getDomain()); + $this->assertEquals('/', $cookies[0]->getPath()); + $this->assertFalse($cookies[0]->isSecure()); + $this->assertFalse($cookies[0]->isHttpOnly()); + + $this->assertEquals('test', $cookies[1]->getName()); + $this->assertNull($cookies[1]->getValue()); + + $this->assertEquals('ABC', $cookies[2]->getName()); + $this->assertEquals('AeD', $cookies[2]->getValue()); + $this->assertEquals(strtotime('Wed, 13 Jan 2021 22:23:01 GMT'), $cookies[2]->getExpiresTime()); + $this->assertEquals('dunglas.fr', $cookies[2]->getDomain()); + $this->assertEquals('/kevin', $cookies[2]->getPath()); + $this->assertTrue($cookies[2]->isSecure()); + $this->assertTrue($cookies[2]->isHttpOnly()); + if (\defined('Symfony\Component\HttpFoundation\Cookie::SAMESITE_STRICT')) { + $this->assertEquals(Cookie::SAMESITE_STRICT, $cookies[2]->getSameSite()); + } + + $this->assertEquals('The response body', $symfonyResponse->getContent()); + $this->assertEquals(200, $symfonyResponse->getStatusCode()); + + $symfonyResponse = $this->factory->createResponse($response, true); + + ob_start(); + $symfonyResponse->sendContent(); + $sentContent = ob_get_clean(); + + $this->assertEquals('The response body', $sentContent); + $this->assertEquals(200, $symfonyResponse->getStatusCode()); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/PsrHttpFactoryTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/PsrHttpFactoryTest.php new file mode 100644 index 000000000..b47cefc18 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Factory/PsrHttpFactoryTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; + +use Nyholm\Psr7\Factory\Psr17Factory; +use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; +use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; + +/** + * @author Kévin Dunglas + * @author Antonio J. García Lagar + */ +class PsrHttpFactoryTest extends AbstractHttpMessageFactoryTest +{ + protected function buildHttpMessageFactory(): HttpMessageFactoryInterface + { + $factory = new Psr17Factory(); + + return new PsrHttpFactory($factory, $factory, $factory, $factory); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php new file mode 100644 index 000000000..18b774189 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php @@ -0,0 +1,45 @@ +responseFactory = $responseFactory; + $this->streamFactory = $streamFactory; + } + + public function serverRequestAction(ServerRequestInterface $request): ResponseInterface + { + return $this->responseFactory + ->createResponse() + ->withBody($this->streamFactory->createStream(sprintf('%s', $request->getMethod()))); + } + + public function requestAction(RequestInterface $request): ResponseInterface + { + return $this->responseFactory + ->createResponse() + ->withStatus(403) + ->withBody($this->streamFactory->createStream(sprintf('%s %s', $request->getMethod(), $request->getBody()->getContents()))); + } + + public function messageAction(MessageInterface $request): ResponseInterface + { + return $this->responseFactory + ->createResponse() + ->withStatus(422) + ->withBody($this->streamFactory->createStream(sprintf('%s', $request->getHeader('X-My-Header')[0]))); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php new file mode 100644 index 000000000..aef819342 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php @@ -0,0 +1,76 @@ +add('server_request', '/server-request')->controller([PsrRequestController::class, 'serverRequestAction'])->methods(['GET']) + ->add('request', '/request')->controller([PsrRequestController::class, 'requestAction'])->methods(['POST']) + ->add('message', '/message')->controller([PsrRequestController::class, 'messageAction'])->methods(['PUT']) + ; + } + + protected function configureContainer(ContainerConfigurator $container): void + { + $container->extension('framework', [ + 'router' => ['utf8' => true], + 'secret' => 'for your eyes only', + 'test' => true, + ]); + + $container->services() + ->set('nyholm.psr_factory', Psr17Factory::class) + ->alias(ResponseFactoryInterface::class, 'nyholm.psr_factory') + ->alias(ServerRequestFactoryInterface::class, 'nyholm.psr_factory') + ->alias(StreamFactoryInterface::class, 'nyholm.psr_factory') + ->alias(UploadedFileFactoryInterface::class, 'nyholm.psr_factory') + ; + + $container->services() + ->defaults()->autowire()->autoconfigure() + ->set(HttpFoundationFactoryInterface::class, HttpFoundationFactory::class) + ->set(HttpMessageFactoryInterface::class, PsrHttpFactory::class) + ->set(PsrResponseListener::class) + ->set(PsrServerRequestResolver::class) + ; + + $container->services() + ->set('logger', NullLogger::class) + ->set(PsrRequestController::class)->public()->autowire() + ; + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php new file mode 100644 index 000000000..e976ae268 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php @@ -0,0 +1,67 @@ +add('/server-request', PsrRequestController::class.'::serverRequestAction')->setMethods(['GET']); + $routes->add('/request', PsrRequestController::class.'::requestAction')->setMethods(['POST']); + $routes->add('/message', PsrRequestController::class.'::messageAction')->setMethods(['PUT']); + } + + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void + { + $container->loadFromExtension('framework', [ + 'secret' => 'for your eyes only', + 'test' => true, + ]); + + $container->register('nyholm.psr_factory', Psr17Factory::class); + $container->setAlias(ResponseFactoryInterface::class, 'nyholm.psr_factory'); + $container->setAlias(ServerRequestFactoryInterface::class, 'nyholm.psr_factory'); + $container->setAlias(StreamFactoryInterface::class, 'nyholm.psr_factory'); + $container->setAlias(UploadedFileFactoryInterface::class, 'nyholm.psr_factory'); + + $container->register(HttpFoundationFactoryInterface::class, HttpFoundationFactory::class)->setAutowired(true)->setAutoconfigured(true); + $container->register(HttpMessageFactoryInterface::class, PsrHttpFactory::class)->setAutowired(true)->setAutoconfigured(true); + $container->register(PsrResponseListener::class)->setAutowired(true)->setAutoconfigured(true); + $container->register(PsrServerRequestResolver::class)->setAutowired(true)->setAutoconfigured(true); + + $container->register('logger', NullLogger::class); + $container->register(PsrRequestController::class)->setPublic(true)->setAutowired(true); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Message.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Message.php new file mode 100644 index 000000000..d561086b9 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Message.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\MessageInterface; +use Psr\Http\Message\StreamInterface; + +/** + * Message. + * + * @author Kévin Dunglas + */ +class Message implements MessageInterface +{ + private $version = '1.1'; + private $headers = []; + private $body; + + public function __construct($version = '1.1', array $headers = [], StreamInterface $body = null) + { + $this->version = $version; + $this->headers = $headers; + $this->body = $body ?? new Stream(); + } + + public function getProtocolVersion(): string + { + return $this->version; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withProtocolVersion($version) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getHeaders(): array + { + return $this->headers; + } + + public function hasHeader($name): bool + { + return isset($this->headers[$name]); + } + + public function getHeader($name): array + { + return $this->hasHeader($name) ? $this->headers[$name] : []; + } + + public function getHeaderLine($name): string + { + return $this->hasHeader($name) ? implode(',', $this->headers[$name]) : ''; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withHeader($name, $value) + { + $this->headers[$name] = (array) $value; + + return $this; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withAddedHeader($name, $value) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withoutHeader($name) + { + unset($this->headers[$name]); + + return $this; + } + + public function getBody(): StreamInterface + { + return $this->body; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withBody(StreamInterface $body) + { + throw new \BadMethodCallException('Not implemented.'); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Response.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Response.php new file mode 100644 index 000000000..0bcf7f406 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Response.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; + +/** + * @author Kévin Dunglas + */ +class Response extends Message implements ResponseInterface +{ + private $statusCode; + + public function __construct($version = '1.1', array $headers = [], StreamInterface $body = null, $statusCode = 200) + { + parent::__construct($version, $headers, $body); + + $this->statusCode = $statusCode; + } + + public function getStatusCode(): int + { + return $this->statusCode; + } + + /** + * @return static + */ + public function withStatus($code, $reasonPhrase = '') + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getReasonPhrase(): string + { + throw new \BadMethodCallException('Not implemented.'); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/ServerRequest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/ServerRequest.php new file mode 100644 index 000000000..b8df06a90 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/ServerRequest.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UriInterface; + +/** + * @author Kévin Dunglas + */ +class ServerRequest extends Message implements ServerRequestInterface +{ + private $requestTarget; + private $method; + private $uri; + private $server; + private $cookies; + private $query; + private $uploadedFiles; + private $data; + private $attributes; + + public function __construct($version = '1.1', array $headers = [], StreamInterface $body = null, $requestTarget = '/', $method = 'GET', $uri = null, array $server = [], array $cookies = [], array $query = [], array $uploadedFiles = [], $data = null, array $attributes = []) + { + parent::__construct($version, $headers, $body); + + $this->requestTarget = $requestTarget; + $this->method = $method; + $this->uri = $uri; + $this->server = $server; + $this->cookies = $cookies; + $this->query = $query; + $this->uploadedFiles = $uploadedFiles; + $this->data = $data; + $this->attributes = $attributes; + } + + public function getRequestTarget(): string + { + return $this->requestTarget; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withRequestTarget($requestTarget) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getMethod(): string + { + return $this->method; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withMethod($method) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return UriInterface + */ + public function getUri() + { + return $this->uri; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withUri(UriInterface $uri, $preserveHost = false) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getServerParams(): array + { + return $this->server; + } + + public function getCookieParams(): array + { + return $this->cookies; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withCookieParams(array $cookies) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getQueryParams(): array + { + return $this->query; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withQueryParams(array $query) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getUploadedFiles(): array + { + return $this->uploadedFiles; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withUploadedFiles(array $uploadedFiles) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return array|object|null + */ + public function getParsedBody() + { + return $this->data; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withParsedBody($data) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function getAttributes(): array + { + return $this->attributes; + } + + /** + * {@inheritdoc} + * + * @return mixed + */ + public function getAttribute($name, $default = null) + { + return $this->attributes[$name] ?? $default; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withAttribute($name, $value) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withoutAttribute($name) + { + throw new \BadMethodCallException('Not implemented.'); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Stream.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Stream.php new file mode 100644 index 000000000..f664bae62 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Stream.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\StreamInterface; + +/** + * @author Kévin Dunglas + */ +class Stream implements StreamInterface +{ + private $stringContent; + private $eof = true; + + public function __construct($stringContent = '') + { + $this->stringContent = $stringContent; + } + + public function __toString(): string + { + return $this->stringContent; + } + + public function close(): void + { + } + + public function detach() + { + return fopen('data://text/plain,'.$this->stringContent, 'r'); + } + + public function getSize(): ?int + { + return null; + } + + public function tell(): int + { + return 0; + } + + public function eof(): bool + { + return $this->eof; + } + + public function isSeekable(): bool + { + return true; + } + + public function seek($offset, $whence = \SEEK_SET): void + { + } + + public function rewind(): void + { + $this->eof = false; + } + + public function isWritable(): bool + { + return false; + } + + public function write($string): int + { + return \strlen($string); + } + + public function isReadable(): bool + { + return true; + } + + public function read($length): string + { + $this->eof = true; + + return $this->stringContent; + } + + public function getContents(): string + { + return $this->stringContent; + } + + /** + * {@inheritdoc} + * + * @return mixed + */ + public function getMetadata($key = null) + { + return null; + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/UploadedFile.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/UploadedFile.php new file mode 100644 index 000000000..900400853 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/UploadedFile.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\UploadedFileInterface; + +/** + * @author Kévin Dunglas + */ +class UploadedFile implements UploadedFileInterface +{ + private $filePath; + private $size; + private $error; + private $clientFileName; + private $clientMediaType; + + public function __construct($filePath, $size = null, $error = \UPLOAD_ERR_OK, $clientFileName = null, $clientMediaType = null) + { + $this->filePath = $filePath; + $this->size = $size; + $this->error = $error; + $this->clientFileName = $clientFileName; + $this->clientMediaType = $clientMediaType; + } + + public function getStream(): Stream + { + return new Stream(file_get_contents($this->filePath)); + } + + public function moveTo($targetPath): void + { + rename($this->filePath, $targetPath); + } + + public function getSize(): ?int + { + return $this->size; + } + + public function getError(): int + { + return $this->error; + } + + public function getClientFilename(): ?string + { + return $this->clientFileName; + } + + public function getClientMediaType(): ?string + { + return $this->clientMediaType; + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Uri.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Uri.php new file mode 100644 index 000000000..48f513d39 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Uri.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\UriInterface; + +/** + * @author Rougin Royce Gutib + */ +class Uri implements UriInterface +{ + private $scheme = ''; + private $userInfo = ''; + private $host = ''; + private $port; + private $path = ''; + private $query = ''; + private $fragment = ''; + private $uriString; + + public function __construct(string $uri = '') + { + $parts = parse_url($uri); + + $this->scheme = $parts['scheme'] ?? ''; + $this->userInfo = $parts['user'] ?? ''; + $this->host = $parts['host'] ?? ''; + $this->port = $parts['port'] ?? null; + $this->path = $parts['path'] ?? ''; + $this->query = $parts['query'] ?? ''; + $this->fragment = $parts['fragment'] ?? ''; + $this->uriString = $uri; + } + + public function getScheme(): string + { + return $this->scheme; + } + + public function getAuthority(): string + { + if (empty($this->host)) { + return ''; + } + + $authority = $this->host; + + if (!empty($this->userInfo)) { + $authority = $this->userInfo.'@'.$authority; + } + + $authority .= ':'.$this->port; + + return $authority; + } + + public function getUserInfo(): string + { + return $this->userInfo; + } + + public function getHost(): string + { + return $this->host; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function getPath(): string + { + return $this->path; + } + + public function getQuery(): string + { + return $this->query; + } + + public function getFragment(): string + { + return $this->fragment; + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withScheme($scheme) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withUserInfo($user, $password = null) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withHost($host) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withPort($port) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withPath($path) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withQuery($query) + { + throw new \BadMethodCallException('Not implemented.'); + } + + /** + * {@inheritdoc} + * + * @return static + */ + public function withFragment($fragment) + { + throw new \BadMethodCallException('Not implemented.'); + } + + public function __toString(): string + { + return $this->uriString; + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php new file mode 100644 index 000000000..0b88405b5 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Functional; + +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Kernel; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Kernel44; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\HttpKernel\Kernel as SymfonyKernel; + +/** + * @author Alexander M. Turek + */ +final class ControllerTest extends WebTestCase +{ + public function testServerRequestAction() + { + $client = self::createClient(); + $crawler = $client->request('GET', '/server-request'); + + self::assertResponseStatusCodeSame(200); + self::assertSame('GET', $crawler->text()); + } + + public function testRequestAction() + { + $client = self::createClient(); + $crawler = $client->request('POST', '/request', [], [], [], 'some content'); + + self::assertResponseStatusCodeSame(403); + self::assertSame('POST some content', $crawler->text()); + } + + public function testMessageAction() + { + $client = self::createClient(); + $crawler = $client->request('PUT', '/message', [], [], ['HTTP_X_MY_HEADER' => 'some content']); + + self::assertResponseStatusCodeSame(422); + self::assertSame('some content', $crawler->text()); + } + + protected static function getKernelClass(): string + { + return SymfonyKernel::VERSION_ID >= 50200 ? Kernel::class : Kernel44::class; + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/CovertTest.php b/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/CovertTest.php new file mode 100644 index 000000000..3d72b7173 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/Tests/Functional/CovertTest.php @@ -0,0 +1,237 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Functional; + +use Nyholm\Psr7\Factory\Psr17Factory; +use Nyholm\Psr7\Response as Psr7Response; +use Nyholm\Psr7\ServerRequest as Psr7Request; +use Nyholm\Psr7\Stream as Psr7Stream; +use PHPUnit\Framework\TestCase; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; +use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; +use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface; +use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Test to convert a request/response back and forth to make sure we do not loose data. + * + * @author Tobias Nyholm + */ +class CovertTest extends TestCase +{ + protected function setUp(): void + { + if (!class_exists(Psr7Request::class)) { + $this->markTestSkipped('nyholm/psr7 is not installed.'); + } + } + + /** + * @dataProvider requestProvider + * + * @param Request|ServerRequestInterface $request + * @param HttpFoundationFactoryInterface|HttpMessageFactoryInterface $firstFactory + * @param HttpFoundationFactoryInterface|HttpMessageFactoryInterface $secondFactory + */ + public function testConvertRequestMultipleTimes($request, $firstFactory, $secondFactory) + { + $temporaryRequest = $firstFactory->createRequest($request); + $finalRequest = $secondFactory->createRequest($temporaryRequest); + + if ($finalRequest instanceof Request) { + $this->assertEquals($request->getBasePath(), $finalRequest->getBasePath()); + $this->assertEquals($request->getBaseUrl(), $finalRequest->getBaseUrl()); + $this->assertEquals($request->getContent(), $finalRequest->getContent()); + $this->assertEquals($request->getEncodings(), $finalRequest->getEncodings()); + $this->assertEquals($request->getETags(), $finalRequest->getETags()); + $this->assertEquals($request->getHost(), $finalRequest->getHost()); + $this->assertEquals($request->getHttpHost(), $finalRequest->getHttpHost()); + $this->assertEquals($request->getMethod(), $finalRequest->getMethod()); + $this->assertEquals($request->getPassword(), $finalRequest->getPassword()); + $this->assertEquals($request->getPathInfo(), $finalRequest->getPathInfo()); + $this->assertEquals($request->getPort(), $finalRequest->getPort()); + $this->assertEquals($request->getProtocolVersion(), $finalRequest->getProtocolVersion()); + $this->assertEquals($request->getQueryString(), $finalRequest->getQueryString()); + $this->assertEquals($request->getRequestUri(), $finalRequest->getRequestUri()); + $this->assertEquals($request->getScheme(), $finalRequest->getScheme()); + $this->assertEquals($request->getSchemeAndHttpHost(), $finalRequest->getSchemeAndHttpHost()); + $this->assertEquals($request->getScriptName(), $finalRequest->getScriptName()); + $this->assertEquals($request->getUri(), $finalRequest->getUri()); + $this->assertEquals($request->getUser(), $finalRequest->getUser()); + $this->assertEquals($request->getUserInfo(), $finalRequest->getUserInfo()); + } elseif ($finalRequest instanceof ServerRequestInterface) { + $strToLower = function ($arr) { + foreach ($arr as $key => $value) { + yield strtolower($key) => $value; + } + }; + $this->assertEquals($request->getAttributes(), $finalRequest->getAttributes()); + $this->assertEquals($request->getCookieParams(), $finalRequest->getCookieParams()); + $this->assertEquals((array) $request->getParsedBody(), (array) $finalRequest->getParsedBody()); + $this->assertEquals($request->getQueryParams(), $finalRequest->getQueryParams()); + // PSR7 does not define a "withServerParams" so this is impossible to implement without knowing the PSR7 implementation. + //$this->assertEquals($request->getServerParams(), $finalRequest->getServerParams()); + $this->assertEquals($request->getUploadedFiles(), $finalRequest->getUploadedFiles()); + $this->assertEquals($request->getMethod(), $finalRequest->getMethod()); + $this->assertEquals($request->getRequestTarget(), $finalRequest->getRequestTarget()); + $this->assertEquals((string) $request->getUri(), (string) $finalRequest->getUri()); + $this->assertEquals((string) $request->getBody(), (string) $finalRequest->getBody()); + $this->assertEquals($strToLower($request->getHeaders()), $strToLower($finalRequest->getHeaders())); + $this->assertEquals($request->getProtocolVersion(), $finalRequest->getProtocolVersion()); + } else { + $this->fail('$finalRequest must be an instance of PSR7 or a HTTPFoundation request'); + } + } + + public function requestProvider() + { + $sfRequest = new Request( + [ + 'foo' => '1', + 'bar' => ['baz' => '42'], + ], + [ + 'twitter' => [ + '@dunglas' => 'Kévin Dunglas', + '@coopTilleuls' => 'Les-Tilleuls.coop', + ], + 'baz' => '2', + ], + [ + 'a2' => ['foo' => 'bar'], + ], + [ + 'c1' => 'foo', + 'c2' => ['c3' => 'bar'], + ], + [ + 'f1' => $this->createUploadedFile('F1', 'f1.txt', 'text/plain', \UPLOAD_ERR_OK), + 'foo' => ['f2' => $this->createUploadedFile('F2', 'f2.txt', 'text/plain', \UPLOAD_ERR_OK)], + ], + [ + 'REQUEST_METHOD' => 'POST', + 'HTTP_HOST' => 'dunglas.fr', + 'SERVER_NAME' => 'dunglas.fr', + 'SERVER_PORT' => null, + 'HTTP_X_SYMFONY' => '2.8', + 'REQUEST_URI' => '/testCreateRequest?foo=1&bar%5Bbaz%5D=42', + 'QUERY_STRING' => 'foo=1&bar%5Bbaz%5D=42', + ], + 'Content' + ); + + $psr7Requests = [ + (new Psr7Request('POST', 'http://tnyholm.se/foo/?bar=biz')) + ->withQueryParams(['bar' => 'biz']), + new Psr7Request('GET', 'https://hey-octave.com/'), + new Psr7Request('GET', 'https://hey-octave.com:443/'), + new Psr7Request('GET', 'https://hey-octave.com:4242/'), + new Psr7Request('GET', 'http://hey-octave.com:80/'), + ]; + + $nyholmFactory = new Psr17Factory(); + $psr17Factory = new PsrHttpFactory($nyholmFactory, $nyholmFactory, $nyholmFactory, $nyholmFactory); + $symfonyFactory = new HttpFoundationFactory(); + + return array_merge([ + [$sfRequest, $psr17Factory, $symfonyFactory], + ], array_map(function ($psr7Request) use ($symfonyFactory, $psr17Factory) { + return [$psr7Request, $symfonyFactory, $psr17Factory]; + }, $psr7Requests)); + } + + /** + * @dataProvider responseProvider + * + * @param Response|ResponseInterface $response + * @param HttpFoundationFactoryInterface|HttpMessageFactoryInterface $firstFactory + * @param HttpFoundationFactoryInterface|HttpMessageFactoryInterface $secondFactory + */ + public function testConvertResponseMultipleTimes($response, $firstFactory, $secondFactory) + { + $temporaryResponse = $firstFactory->createResponse($response); + $finalResponse = $secondFactory->createResponse($temporaryResponse); + + if ($finalResponse instanceof Response) { + $this->assertEquals($response->getAge(), $finalResponse->getAge()); + $this->assertEquals($response->getCharset(), $finalResponse->getCharset()); + $this->assertEquals($response->getContent(), $finalResponse->getContent()); + $this->assertEquals($response->getDate(), $finalResponse->getDate()); + $this->assertEquals($response->getEtag(), $finalResponse->getEtag()); + $this->assertEquals($response->getExpires(), $finalResponse->getExpires()); + $this->assertEquals($response->getLastModified(), $finalResponse->getLastModified()); + $this->assertEquals($response->getMaxAge(), $finalResponse->getMaxAge()); + $this->assertEquals($response->getProtocolVersion(), $finalResponse->getProtocolVersion()); + $this->assertEquals($response->getStatusCode(), $finalResponse->getStatusCode()); + $this->assertEquals($response->getTtl(), $finalResponse->getTtl()); + } elseif ($finalResponse instanceof ResponseInterface) { + $strToLower = function ($arr) { + foreach ($arr as $key => $value) { + yield strtolower($key) => $value; + } + }; + $this->assertEquals($response->getStatusCode(), $finalResponse->getStatusCode()); + $this->assertEquals($response->getReasonPhrase(), $finalResponse->getReasonPhrase()); + $this->assertEquals((string) $response->getBody(), (string) $finalResponse->getBody()); + $this->assertEquals($strToLower($response->getHeaders()), $strToLower($finalResponse->getHeaders())); + $this->assertEquals($response->getProtocolVersion(), $finalResponse->getProtocolVersion()); + } else { + $this->fail('$finalResponse must be an instance of PSR7 or a HTTPFoundation response'); + } + } + + public function responseProvider() + { + $sfResponse = new Response( + 'Response content.', + 202, + ['x-symfony' => ['3.4']] + ); + + if (method_exists(Cookie::class, 'create')) { + $cookie = Cookie::create('city', 'Lille', new \DateTime('Wed, 13 Jan 2021 22:23:01 GMT')); + } else { + $cookie = new Cookie('city', 'Lille', new \DateTime('Wed, 13 Jan 2021 22:23:01 GMT')); + } + + $sfResponse->headers->setCookie($cookie); + $body = Psr7Stream::create(); + $status = 302; + $headers = [ + 'location' => ['http://example.com/'], + ]; + $zendResponse = new Psr7Response($status, $headers, $body); + + $nyholmFactory = new Psr17Factory(); + $psr17Factory = new PsrHttpFactory($nyholmFactory, $nyholmFactory, $nyholmFactory, $nyholmFactory); + $symfonyFactory = new HttpFoundationFactory(); + + return [ + [$sfResponse, $psr17Factory, $symfonyFactory], + [$zendResponse, $symfonyFactory, $psr17Factory], + ]; + } + + private function createUploadedFile($content, $originalName, $mimeType, $error) + { + $path = tempnam(sys_get_temp_dir(), uniqid()); + file_put_contents($path, $content); + + return new UploadedFile($path, $originalName, $mimeType, $error, true); + } +} diff --git a/src/vendor/symfony/psr-http-message-bridge/composer.json b/src/vendor/symfony/psr-http-message-bridge/composer.json index b705eb2e2..028230744 100644 --- a/src/vendor/symfony/psr-http-message-bridge/composer.json +++ b/src/vendor/symfony/psr-http-message-bridge/composer.json @@ -16,18 +16,17 @@ } ], "require": { - "php": ">=7.2.5", - "psr/http-message": "^1.0 || ^2.0", - "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/http-foundation": "^5.4 || ^6.0" + "php": ">=7.1", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^4.4 || ^5.0 || ^6.0" }, "require-dev": { - "symfony/browser-kit": "^5.4 || ^6.0", - "symfony/config": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/framework-bundle": "^5.4 || ^6.0", - "symfony/http-kernel": "^5.4 || ^6.0", - "symfony/phpunit-bridge": "^6.2", + "symfony/browser-kit": "^4.4 || ^5.0 || ^6.0", + "symfony/config": "^4.4 || ^5.0 || ^6.0", + "symfony/event-dispatcher": "^4.4 || ^5.0 || ^6.0", + "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0", + "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0", + "symfony/phpunit-bridge": "^5.4@dev || ^6.0", "nyholm/psr7": "^1.1", "psr/log": "^1.1 || ^2 || ^3" }, @@ -42,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.3-dev" + "dev-main": "2.1-dev" } } } diff --git a/src/vendor/symfony/psr-http-message-bridge/phpunit.xml.dist b/src/vendor/symfony/psr-http-message-bridge/phpunit.xml.dist new file mode 100644 index 000000000..43aeaa338 --- /dev/null +++ b/src/vendor/symfony/psr-http-message-bridge/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/vendor/symfony/service-contracts/LICENSE b/src/vendor/symfony/service-contracts/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/src/vendor/symfony/service-contracts/LICENSE +++ b/src/vendor/symfony/service-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php index 6c560a427..f7fc2df6a 100644 --- a/src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php +++ b/src/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -30,6 +30,12 @@ trait ServiceSubscriberTrait */ public static function getSubscribedServices(): array { + static $services; + + if (null !== $services) { + return $services; + } + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; $attributeOptIn = false; @@ -98,13 +104,12 @@ trait ServiceSubscriberTrait */ public function setContainer(ContainerInterface $container) { - $ret = null; - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - $ret = parent::setContainer($container); - } - $this->container = $container; - return $ret; + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + return parent::setContainer($container); + } + + return null; } } diff --git a/src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php index 07d12b4a5..2a1b565f5 100644 --- a/src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +++ b/src/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -11,13 +11,85 @@ namespace Symfony\Contracts\Service\Test; -class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; -if (false) { +abstract class ServiceLocatorTest extends TestCase +{ /** - * @deprecated since PHPUnit 9.6 + * @return ContainerInterface */ - class ServiceLocatorTest + protected function getServiceLocator(array $factories) { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); } } diff --git a/src/vendor/symfony/translation-contracts/LICENSE b/src/vendor/symfony/translation-contracts/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/src/vendor/symfony/translation-contracts/LICENSE +++ b/src/vendor/symfony/translation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/translation-contracts/Test/TranslatorTest.php b/src/vendor/symfony/translation-contracts/Test/TranslatorTest.php index dff86ddad..890367657 100644 --- a/src/vendor/symfony/translation-contracts/Test/TranslatorTest.php +++ b/src/vendor/symfony/translation-contracts/Test/TranslatorTest.php @@ -117,7 +117,7 @@ class TranslatorTest extends TestCase $this->assertEquals('en', $translator->getLocale()); } - public static function getTransTests() + public function getTransTests() { return [ ['Symfony is great!', 'Symfony is great!', []], @@ -125,7 +125,7 @@ class TranslatorTest extends TestCase ]; } - public static function getTransChoiceTests() + public function getTransChoiceTests() { return [ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], @@ -140,7 +140,7 @@ class TranslatorTest extends TestCase } /** - * @dataProvider getInterval + * @dataProvider getInternal */ public function testInterval($expected, $number, $interval) { @@ -149,7 +149,7 @@ class TranslatorTest extends TestCase $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number])); } - public static function getInterval() + public function getInternal() { return [ ['foo', 3, '{1,2, 3 ,4}'], @@ -192,7 +192,7 @@ class TranslatorTest extends TestCase $translator->trans($id, ['%count%' => $number]); } - public static function getNonMatchingMessages() + public function getNonMatchingMessages() { return [ ['{0} There are no apples|{1} There is one apple', 2], @@ -202,7 +202,7 @@ class TranslatorTest extends TestCase ]; } - public static function getChooseTests() + public function getChooseTests() { return [ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], @@ -258,13 +258,13 @@ class TranslatorTest extends TestCase new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 5], - // with double-quotes and id split across lines + // with double-quotes and id split accros lines ['This is a text with a new-line in it. Selector = 1.', '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 1], - // with single-quotes and id split across lines + // with single-quotes and id split accros lines ['This is a text with a new-line in it. Selector > 1.', '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a @@ -272,9 +272,9 @@ class TranslatorTest extends TestCase new-line in it. Selector > 1.', 5], // with single-quotes and \n in text ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0], - // with double-quotes and id split across lines + // with double-quotes and id split accros lines ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1], - // escape pipe + // esacape pipe ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0], // Empty plural set (2 plural forms) from a .PO file ['', '|', 1], @@ -320,7 +320,7 @@ class TranslatorTest extends TestCase * * @return array */ - public static function successLangcodes() + public function successLangcodes() { return [ ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']], @@ -339,7 +339,7 @@ class TranslatorTest extends TestCase * * @return array with nplural together with langcodes */ - public static function failingLangcodes() + public function failingLangcodes() { return [ ['1', ['fa']], @@ -362,7 +362,7 @@ class TranslatorTest extends TestCase foreach ($matrix as $langCode => $data) { $indexes = array_flip($data); if ($expectSuccess) { - $this->assertCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms."); + $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); } else { $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); } diff --git a/src/vendor/symfony/translation-contracts/TranslatableInterface.php b/src/vendor/symfony/translation-contracts/TranslatableInterface.php index 8554697ec..47fd6fa02 100644 --- a/src/vendor/symfony/translation-contracts/TranslatableInterface.php +++ b/src/vendor/symfony/translation-contracts/TranslatableInterface.php @@ -16,5 +16,5 @@ namespace Symfony\Contracts\Translation; */ interface TranslatableInterface { - public function trans(TranslatorInterface $translator, ?string $locale = null): string; + public function trans(TranslatorInterface $translator, string $locale = null): string; } diff --git a/src/vendor/symfony/translation-contracts/TranslatorInterface.php b/src/vendor/symfony/translation-contracts/TranslatorInterface.php index 85ca166bf..77b7a9c58 100644 --- a/src/vendor/symfony/translation-contracts/TranslatorInterface.php +++ b/src/vendor/symfony/translation-contracts/TranslatorInterface.php @@ -63,5 +63,5 @@ interface TranslatorInterface * * @throws \InvalidArgumentException If the locale contains invalid characters */ - public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null); + public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null); } diff --git a/src/vendor/symfony/translation-contracts/TranslatorTrait.php b/src/vendor/symfony/translation-contracts/TranslatorTrait.php index ac01d730a..405ce8d70 100644 --- a/src/vendor/symfony/translation-contracts/TranslatorTrait.php +++ b/src/vendor/symfony/translation-contracts/TranslatorTrait.php @@ -43,7 +43,7 @@ trait TranslatorTrait /** * {@inheritdoc} */ - public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string { if (null === $id || '' === $id) { return ''; diff --git a/src/vendor/symfony/translation/CHANGELOG.md b/src/vendor/symfony/translation/CHANGELOG.md index 93615dcac..160b5e694 100644 --- a/src/vendor/symfony/translation/CHANGELOG.md +++ b/src/vendor/symfony/translation/CHANGELOG.md @@ -1,13 +1,6 @@ CHANGELOG ========= -5.4.21 ------- - - * [BC BREAK] The following data providers for `ProviderFactoryTestCase` are now static: - `supportsProvider()`, `createProvider()`, `unsupportedSchemeProvider()`and `incompleteDsnProvider()` - * [BC BREAK] `ProviderTestCase::toStringProvider()` is now static - 5.4 --- diff --git a/src/vendor/symfony/translation/Command/TranslationPullCommand.php b/src/vendor/symfony/translation/Command/TranslationPullCommand.php index e2e7c00dc..52da595c6 100644 --- a/src/vendor/symfony/translation/Command/TranslationPullCommand.php +++ b/src/vendor/symfony/translation/Command/TranslationPullCommand.php @@ -142,7 +142,7 @@ EOF switch ($format) { case 'xlf20': $xliffVersion = '2.0'; - // no break + // no break case 'xlf12': $format = 'xlf'; } @@ -160,7 +160,7 @@ EOF if ($force) { foreach ($providerTranslations->getCatalogues() as $catalogue) { - $operation = new TargetOperation(new MessageCatalogue($catalogue->getLocale()), $catalogue); + $operation = new TargetOperation((new MessageCatalogue($catalogue->getLocale())), $catalogue); if ($intlIcu) { $operation->moveMessagesToIntlDomainsIfPossible(); } diff --git a/src/vendor/symfony/translation/Command/TranslationPushCommand.php b/src/vendor/symfony/translation/Command/TranslationPushCommand.php index bf6e8c948..973ed5fe1 100644 --- a/src/vendor/symfony/translation/Command/TranslationPushCommand.php +++ b/src/vendor/symfony/translation/Command/TranslationPushCommand.php @@ -131,16 +131,16 @@ EOF $force = $input->getOption('force'); $deleteMissing = $input->getOption('delete-missing'); - if (!$domains && $provider instanceof FilteringProvider) { - $domains = $provider->getDomains(); - } - - // Reading local translations must be done after retrieving the domains from the provider - // in order to manage only translations from configured domains $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths); if (!$domains) { - $domains = $this->getDomainsFromTranslatorBag($localTranslations); + if ($provider instanceof FilteringProvider) { + $domains = $provider->getDomains(); + } + + if (!$domains) { + $domains = $this->getDomainsFromTranslatorBag($localTranslations); + } } if (!$deleteMissing && $force) { diff --git a/src/vendor/symfony/translation/Command/XliffLintCommand.php b/src/vendor/symfony/translation/Command/XliffLintCommand.php index 0a0bc0ee6..fb2b5f31c 100644 --- a/src/vendor/symfony/translation/Command/XliffLintCommand.php +++ b/src/vendor/symfony/translation/Command/XliffLintCommand.php @@ -42,7 +42,7 @@ class XliffLintCommand extends Command private $isReadableProvider; private $requireStrictFileNames; - public function __construct(?string $name = null, ?callable $directoryIteratorProvider = null, ?callable $isReadableProvider = null, bool $requireStrictFileNames = true) + public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true) { parent::__construct($name); @@ -111,7 +111,7 @@ EOF return $this->display($io, $filesInfo); } - private function validate(string $content, ?string $file = null): array + private function validate(string $content, string $file = null): array { $errors = []; diff --git a/src/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/src/vendor/symfony/translation/DataCollector/TranslationDataCollector.php index 12c1d04ae..379130a44 100644 --- a/src/vendor/symfony/translation/DataCollector/TranslationDataCollector.php +++ b/src/vendor/symfony/translation/DataCollector/TranslationDataCollector.php @@ -48,7 +48,7 @@ class TranslationDataCollector extends DataCollector implements LateDataCollecto /** * {@inheritdoc} */ - public function collect(Request $request, Response $response, ?\Throwable $exception = null) + public function collect(Request $request, Response $response, \Throwable $exception = null) { $this->data['locale'] = $this->translator->getLocale(); $this->data['fallback_locales'] = $this->translator->getFallbackLocales(); diff --git a/src/vendor/symfony/translation/DataCollectorTranslator.php b/src/vendor/symfony/translation/DataCollectorTranslator.php index 6de5e22a3..ea5a2dd5e 100644 --- a/src/vendor/symfony/translation/DataCollectorTranslator.php +++ b/src/vendor/symfony/translation/DataCollectorTranslator.php @@ -43,7 +43,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter /** * {@inheritdoc} */ - public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null) + public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null) { $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale); $this->collectMessage($locale, $domain, $id, $trans, $parameters); @@ -70,7 +70,7 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter /** * {@inheritdoc} */ - public function getCatalogue(?string $locale = null) + public function getCatalogue(string $locale = null) { return $this->translator->getCatalogue($locale); } diff --git a/src/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/src/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php index 2ee13640c..18a71c45a 100644 --- a/src/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php +++ b/src/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php @@ -16,7 +16,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; /** * @author Yonel Ceruto @@ -137,20 +136,28 @@ class TranslatorPathsPass extends AbstractRecursivePass private function findControllerArguments(ContainerBuilder $container): array { - if (!$container->has($this->resolverServiceId)) { - return []; - } - $resolverDef = $container->findDefinition($this->resolverServiceId); + if ($container->hasDefinition($this->resolverServiceId)) { + $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } - if (TraceableValueResolver::class === $resolverDef->getClass()) { - $resolverDef = $container->getDefinition($resolverDef->getArgument(0)); + return $argument->getArgument(0); } - $argument = $resolverDef->getArgument(0); - if ($argument instanceof Reference) { - $argument = $container->getDefinition($argument); + if ($container->hasDefinition('debug.'.$this->resolverServiceId)) { + $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + $argument = $argument->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + + return $argument->getArgument(0); } - return $argument->getArgument(0); + return []; } } diff --git a/src/vendor/symfony/translation/Dumper/CsvFileDumper.php b/src/vendor/symfony/translation/Dumper/CsvFileDumper.php index 3bb41f16b..0c8589af8 100644 --- a/src/vendor/symfony/translation/Dumper/CsvFileDumper.php +++ b/src/vendor/symfony/translation/Dumper/CsvFileDumper.php @@ -31,7 +31,7 @@ class CsvFileDumper extends FileDumper $handle = fopen('php://memory', 'r+'); foreach ($messages->all($domain) as $source => $target) { - fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure, '\\'); + fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure); } rewind($handle); diff --git a/src/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/src/vendor/symfony/translation/Dumper/IcuResFileDumper.php index 12a7a8cfc..cdc59913b 100644 --- a/src/vendor/symfony/translation/Dumper/IcuResFileDumper.php +++ b/src/vendor/symfony/translation/Dumper/IcuResFileDumper.php @@ -47,7 +47,7 @@ class IcuResFileDumper extends FileDumper $data .= pack('V', \strlen($target)) .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') .$this->writePadding($data) - ; + ; } $resOffset = $this->getPosition($data); @@ -56,7 +56,7 @@ class IcuResFileDumper extends FileDumper .$indexes .$this->writePadding($data) .$resources - ; + ; $bundleTop = $this->getPosition($data); diff --git a/src/vendor/symfony/translation/Dumper/MoFileDumper.php b/src/vendor/symfony/translation/Dumper/MoFileDumper.php index f52206ee3..54d0da875 100644 --- a/src/vendor/symfony/translation/Dumper/MoFileDumper.php +++ b/src/vendor/symfony/translation/Dumper/MoFileDumper.php @@ -62,7 +62,7 @@ class MoFileDumper extends FileDumper .$targetOffsets .$sources .$targets - ; + ; return $output; } diff --git a/src/vendor/symfony/translation/Dumper/XliffFileDumper.php b/src/vendor/symfony/translation/Dumper/XliffFileDumper.php index a480b3f23..f7dbdcddf 100644 --- a/src/vendor/symfony/translation/Dumper/XliffFileDumper.php +++ b/src/vendor/symfony/translation/Dumper/XliffFileDumper.php @@ -196,7 +196,7 @@ class XliffFileDumper extends FileDumper return $dom->saveXML(); } - private function hasMetadataArrayInfo(string $key, ?array $metadata = null): bool + private function hasMetadataArrayInfo(string $key, array $metadata = null): bool { return is_iterable($metadata[$key] ?? null); } diff --git a/src/vendor/symfony/translation/Exception/IncompleteDsnException.php b/src/vendor/symfony/translation/Exception/IncompleteDsnException.php index b304bde01..cb0ce027e 100644 --- a/src/vendor/symfony/translation/Exception/IncompleteDsnException.php +++ b/src/vendor/symfony/translation/Exception/IncompleteDsnException.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Translation\Exception; class IncompleteDsnException extends InvalidArgumentException { - public function __construct(string $message, ?string $dsn = null, ?\Throwable $previous = null) + public function __construct(string $message, string $dsn = null, \Throwable $previous = null) { if ($dsn) { $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message; diff --git a/src/vendor/symfony/translation/Exception/MissingRequiredOptionException.php b/src/vendor/symfony/translation/Exception/MissingRequiredOptionException.php index 46152e254..2b5f80806 100644 --- a/src/vendor/symfony/translation/Exception/MissingRequiredOptionException.php +++ b/src/vendor/symfony/translation/Exception/MissingRequiredOptionException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\Translation\Exception; */ class MissingRequiredOptionException extends IncompleteDsnException { - public function __construct(string $option, ?string $dsn = null, ?\Throwable $previous = null) + public function __construct(string $option, string $dsn = null, \Throwable $previous = null) { $message = sprintf('The option "%s" is required but missing.', $option); diff --git a/src/vendor/symfony/translation/Exception/ProviderException.php b/src/vendor/symfony/translation/Exception/ProviderException.php index 8b909fe27..571920da3 100644 --- a/src/vendor/symfony/translation/Exception/ProviderException.php +++ b/src/vendor/symfony/translation/Exception/ProviderException.php @@ -21,7 +21,7 @@ class ProviderException extends RuntimeException implements ProviderExceptionInt private $response; private $debug; - public function __construct(string $message, ResponseInterface $response, int $code = 0, ?\Exception $previous = null) + public function __construct(string $message, ResponseInterface $response, int $code = 0, \Exception $previous = null) { $this->response = $response; $this->debug = $response->getInfo('debug') ?? ''; diff --git a/src/vendor/symfony/translation/Exception/UnsupportedSchemeException.php b/src/vendor/symfony/translation/Exception/UnsupportedSchemeException.php index 800c4cdb6..7fbaa8f04 100644 --- a/src/vendor/symfony/translation/Exception/UnsupportedSchemeException.php +++ b/src/vendor/symfony/translation/Exception/UnsupportedSchemeException.php @@ -31,7 +31,7 @@ class UnsupportedSchemeException extends LogicException ], ]; - public function __construct(Dsn $dsn, ?string $name = null, array $supported = []) + public function __construct(Dsn $dsn, string $name = null, array $supported = []) { $provider = $dsn->getScheme(); if (false !== $pos = strpos($provider, '+')) { diff --git a/src/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/src/vendor/symfony/translation/Extractor/PhpStringTokenParser.php index c0699461d..d114cc738 100644 --- a/src/vendor/symfony/translation/Extractor/PhpStringTokenParser.php +++ b/src/vendor/symfony/translation/Extractor/PhpStringTokenParser.php @@ -93,7 +93,7 @@ class PhpStringTokenParser * * @return string */ - public static function parseEscapeSequences(string $str, ?string $quote = null) + public static function parseEscapeSequences(string $str, string $quote = null) { if (null !== $quote) { $str = str_replace('\\'.$quote, $quote, $str); diff --git a/src/vendor/symfony/translation/Formatter/MessageFormatter.php b/src/vendor/symfony/translation/Formatter/MessageFormatter.php index 3449a84a5..040796483 100644 --- a/src/vendor/symfony/translation/Formatter/MessageFormatter.php +++ b/src/vendor/symfony/translation/Formatter/MessageFormatter.php @@ -28,7 +28,7 @@ class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterf /** * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization */ - public function __construct(?TranslatorInterface $translator = null, ?IntlFormatterInterface $intlFormatter = null) + public function __construct(TranslatorInterface $translator = null, IntlFormatterInterface $intlFormatter = null) { $this->translator = $translator ?? new IdentityTranslator(); $this->intlFormatter = $intlFormatter ?? new IntlFormatter(); diff --git a/src/vendor/symfony/translation/LICENSE b/src/vendor/symfony/translation/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/src/vendor/symfony/translation/LICENSE +++ b/src/vendor/symfony/translation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/translation/Loader/ArrayLoader.php b/src/vendor/symfony/translation/Loader/ArrayLoader.php index feed0de4b..0758da8b5 100644 --- a/src/vendor/symfony/translation/Loader/ArrayLoader.php +++ b/src/vendor/symfony/translation/Loader/ArrayLoader.php @@ -46,11 +46,9 @@ class ArrayLoader implements LoaderInterface foreach ($messages as $key => $value) { if (\is_array($value)) { foreach ($this->flatten($value) as $k => $v) { - if (null !== $v) { - $result[$key.'.'.$k] = $v; - } + $result[$key.'.'.$k] = $v; } - } elseif (null !== $value) { + } else { $result[$key] = $value; } } diff --git a/src/vendor/symfony/translation/Loader/CsvFileLoader.php b/src/vendor/symfony/translation/Loader/CsvFileLoader.php index 0cf05731b..8d5d4db9a 100644 --- a/src/vendor/symfony/translation/Loader/CsvFileLoader.php +++ b/src/vendor/symfony/translation/Loader/CsvFileLoader.php @@ -22,7 +22,7 @@ class CsvFileLoader extends FileLoader { private $delimiter = ';'; private $enclosure = '"'; - private $escape = ''; + private $escape = '\\'; /** * {@inheritdoc} @@ -38,7 +38,7 @@ class CsvFileLoader extends FileLoader } $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); - $file->setCsvControl($this->delimiter, $this->enclosure, '' === $this->escape && \PHP_VERSION_ID < 70400 ? '\\' : $this->escape); + $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); foreach ($file as $data) { if (false === $data) { @@ -56,10 +56,10 @@ class CsvFileLoader extends FileLoader /** * Sets the delimiter, enclosure, and escape character for CSV. */ - public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '') + public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '\\') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; - $this->escape = '' === $escape && \PHP_VERSION_ID < 70400 ? '\\' : $escape; + $this->escape = $escape; } } diff --git a/src/vendor/symfony/translation/Loader/IcuResFileLoader.php b/src/vendor/symfony/translation/Loader/IcuResFileLoader.php index 88e133738..7e3391ecb 100644 --- a/src/vendor/symfony/translation/Loader/IcuResFileLoader.php +++ b/src/vendor/symfony/translation/Loader/IcuResFileLoader.php @@ -71,11 +71,11 @@ class IcuResFileLoader implements LoaderInterface * * @param \ResourceBundle $rb The ResourceBundle that will be flattened * @param array $messages Used internally for recursive calls - * @param string|null $path Current path being parsed, used internally for recursive calls + * @param string $path Current path being parsed, used internally for recursive calls * * @return array */ - protected function flatten(\ResourceBundle $rb, array &$messages = [], ?string $path = null) + protected function flatten(\ResourceBundle $rb, array &$messages = [], string $path = null) { foreach ($rb as $key => $value) { $nodePath = $path ? $path.'.'.$key : $key; diff --git a/src/vendor/symfony/translation/Loader/PhpFileLoader.php b/src/vendor/symfony/translation/Loader/PhpFileLoader.php index 40f64db27..85f10902b 100644 --- a/src/vendor/symfony/translation/Loader/PhpFileLoader.php +++ b/src/vendor/symfony/translation/Loader/PhpFileLoader.php @@ -25,7 +25,7 @@ class PhpFileLoader extends FileLoader */ protected function loadResource(string $resource) { - if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { + if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { self::$cache = null; } diff --git a/src/vendor/symfony/translation/Loader/XliffFileLoader.php b/src/vendor/symfony/translation/Loader/XliffFileLoader.php index f4d239619..5c9794a54 100644 --- a/src/vendor/symfony/translation/Loader/XliffFileLoader.php +++ b/src/vendor/symfony/translation/Loader/XliffFileLoader.php @@ -111,20 +111,12 @@ class XliffFileLoader implements LoaderInterface continue; } - $source = (string) (isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source); - - if (isset($translation->target) - && 'needs-translation' === (string) $translation->target->attributes()['state'] - && \in_array((string) $translation->target, [$source, (string) $translation->source], true) - ) { - continue; - } - + $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; // If the xlf file has another encoding specified, try to convert it because // simple_xml will always return utf-8 encoded values $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding); - $catalogue->set($source, $target, $domain); + $catalogue->set((string) $source, $target, $domain); $metadata = [ 'source' => (string) $translation->source, @@ -147,7 +139,7 @@ class XliffFileLoader implements LoaderInterface $metadata['id'] = (string) $attributes['id']; } - $catalogue->setMetadata($source, $metadata, $domain); + $catalogue->setMetadata((string) $source, $metadata, $domain); } } } @@ -198,7 +190,7 @@ class XliffFileLoader implements LoaderInterface /** * Convert a UTF8 string to the specified encoding. */ - private function utf8ToCharset(string $content, ?string $encoding = null): string + private function utf8ToCharset(string $content, string $encoding = null): string { if ('UTF-8' !== $encoding && !empty($encoding)) { return mb_convert_encoding($content, $encoding, 'UTF-8'); @@ -207,7 +199,7 @@ class XliffFileLoader implements LoaderInterface return $content; } - private function parseNotesMetadata(?\SimpleXMLElement $noteElement = null, ?string $encoding = null): array + private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array { $notes = []; diff --git a/src/vendor/symfony/translation/LoggingTranslator.php b/src/vendor/symfony/translation/LoggingTranslator.php index d0932b667..6ccd48289 100644 --- a/src/vendor/symfony/translation/LoggingTranslator.php +++ b/src/vendor/symfony/translation/LoggingTranslator.php @@ -40,7 +40,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, /** * {@inheritdoc} */ - public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null) + public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null) { $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale); $this->log($id, $domain, $locale); @@ -73,7 +73,7 @@ class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, /** * {@inheritdoc} */ - public function getCatalogue(?string $locale = null) + public function getCatalogue(string $locale = null) { return $this->translator->getCatalogue($locale); } diff --git a/src/vendor/symfony/translation/MessageCatalogue.php b/src/vendor/symfony/translation/MessageCatalogue.php index 2e00b645e..ff49b5a97 100644 --- a/src/vendor/symfony/translation/MessageCatalogue.php +++ b/src/vendor/symfony/translation/MessageCatalogue.php @@ -63,7 +63,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf /** * {@inheritdoc} */ - public function all(?string $domain = null) + public function all(string $domain = null) { if (null !== $domain) { // skip messages merge if intl-icu requested explicitly @@ -155,14 +155,19 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf */ public function add(array $messages, string $domain = 'messages') { - $altDomain = str_ends_with($domain, self::INTL_DOMAIN_SUFFIX) ? substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)) : $domain.self::INTL_DOMAIN_SUFFIX; - foreach ($messages as $id => $message) { - unset($this->messages[$altDomain][$id]); - $this->messages[$domain][$id] = $message; + if (!isset($this->messages[$domain])) { + $this->messages[$domain] = []; } - - if ([] === ($this->messages[$altDomain] ?? null)) { - unset($this->messages[$altDomain]); + $intlDomain = $domain; + if (!str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { + $intlDomain .= self::INTL_DOMAIN_SUFFIX; + } + foreach ($messages as $id => $message) { + if (isset($this->messages[$intlDomain]) && \array_key_exists($id, $this->messages[$intlDomain])) { + $this->messages[$intlDomain][$id] = $message; + } else { + $this->messages[$domain][$id] = $message; + } } } diff --git a/src/vendor/symfony/translation/MessageCatalogueInterface.php b/src/vendor/symfony/translation/MessageCatalogueInterface.php index d532a1e48..cf7746c23 100644 --- a/src/vendor/symfony/translation/MessageCatalogueInterface.php +++ b/src/vendor/symfony/translation/MessageCatalogueInterface.php @@ -41,11 +41,11 @@ interface MessageCatalogueInterface * * If $domain is null, it returns all messages. * - * @param string|null $domain The domain name + * @param string $domain The domain name * * @return array */ - public function all(?string $domain = null); + public function all(string $domain = null); /** * Sets a message translation. diff --git a/src/vendor/symfony/translation/Provider/AbstractProviderFactory.php b/src/vendor/symfony/translation/Provider/AbstractProviderFactory.php index fdfeb8ce3..17442fde8 100644 --- a/src/vendor/symfony/translation/Provider/AbstractProviderFactory.php +++ b/src/vendor/symfony/translation/Provider/AbstractProviderFactory.php @@ -28,7 +28,7 @@ abstract class AbstractProviderFactory implements ProviderFactoryInterface protected function getUser(Dsn $dsn): string { if (null === $user = $dsn->getUser()) { - throw new IncompleteDsnException('User is not set.', $dsn->getScheme().'://'.$dsn->getHost()); + throw new IncompleteDsnException('User is not set.', $dsn->getOriginalDsn()); } return $user; diff --git a/src/vendor/symfony/translation/Provider/Dsn.php b/src/vendor/symfony/translation/Provider/Dsn.php index d29b202d1..820cabfb3 100644 --- a/src/vendor/symfony/translation/Provider/Dsn.php +++ b/src/vendor/symfony/translation/Provider/Dsn.php @@ -33,25 +33,25 @@ final class Dsn { $this->originalDsn = $dsn; - if (false === $params = parse_url($dsn)) { - throw new InvalidArgumentException('The translation provider DSN is invalid.'); + if (false === $parsedDsn = parse_url($dsn)) { + throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN is invalid.', $dsn)); } - if (!isset($params['scheme'])) { - throw new InvalidArgumentException('The translation provider DSN must contain a scheme.'); + if (!isset($parsedDsn['scheme'])) { + throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a scheme.', $dsn)); } - $this->scheme = $params['scheme']; + $this->scheme = $parsedDsn['scheme']; - if (!isset($params['host'])) { - throw new InvalidArgumentException('The translation provider DSN must contain a host (use "default" by default).'); + if (!isset($parsedDsn['host'])) { + throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a host (use "default" by default).', $dsn)); } - $this->host = $params['host']; + $this->host = $parsedDsn['host']; - $this->user = '' !== ($params['user'] ?? '') ? rawurldecode($params['user']) : null; - $this->password = '' !== ($params['pass'] ?? '') ? rawurldecode($params['pass']) : null; - $this->port = $params['port'] ?? null; - $this->path = $params['path'] ?? null; - parse_str($params['query'] ?? '', $this->options); + $this->user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null; + $this->password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null; + $this->port = $parsedDsn['port'] ?? null; + $this->path = $parsedDsn['path'] ?? null; + parse_str($parsedDsn['query'] ?? '', $this->options); } public function getScheme(): string @@ -74,7 +74,7 @@ final class Dsn return $this->password; } - public function getPort(?int $default = null): ?int + public function getPort(int $default = null): ?int { return $this->port ?? $default; } diff --git a/src/vendor/symfony/translation/PseudoLocalizationTranslator.php b/src/vendor/symfony/translation/PseudoLocalizationTranslator.php index 5396eb546..e004986a5 100644 --- a/src/vendor/symfony/translation/PseudoLocalizationTranslator.php +++ b/src/vendor/symfony/translation/PseudoLocalizationTranslator.php @@ -86,7 +86,7 @@ final class PseudoLocalizationTranslator implements TranslatorInterface /** * {@inheritdoc} */ - public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string { $trans = ''; $visibleText = ''; @@ -123,7 +123,7 @@ final class PseudoLocalizationTranslator implements TranslatorInterface return [[true, true, $originalTrans]]; } - $html = mb_encode_numericentity($originalTrans, [0x80, 0x10FFFF, 0, 0x1FFFFF], mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8'); + $html = mb_encode_numericentity($originalTrans, [0x80, 0xFFFF, 0, 0xFFFF], mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8'); $useInternalErrors = libxml_use_internal_errors(true); @@ -283,7 +283,7 @@ final class PseudoLocalizationTranslator implements TranslatorInterface } $visibleLength = $this->strlen($visibleText); - $missingLength = (int) ceil($visibleLength * $this->expansionFactor) - $visibleLength; + $missingLength = (int) (ceil($visibleLength * $this->expansionFactor)) - $visibleLength; if ($this->brackets) { $missingLength -= 2; } diff --git a/src/vendor/symfony/translation/Resources/bin/translation-status.php b/src/vendor/symfony/translation/Resources/bin/translation-status.php index 1ab72c000..fac8acbad 100644 --- a/src/vendor/symfony/translation/Resources/bin/translation-status.php +++ b/src/vendor/symfony/translation/Resources/bin/translation-status.php @@ -9,10 +9,6 @@ * file that was distributed with this source code. */ -if ('cli' !== \PHP_SAPI) { - throw new Exception('This script must be run from the command line.'); -} - $usageInstructions = <<file->body->{'trans-unit'} as $translationKey) { $translationId = (string) $translationKey['id']; - $translationKey = (string) ($translationKey['resname'] ?? $translationKey->source); + $translationKey = (string) $translationKey->source; $translationKeys[$translationId] = $translationKey; } diff --git a/src/vendor/symfony/translation/Resources/data/parents.json b/src/vendor/symfony/translation/Resources/data/parents.json index 24d4d119e..32a33cdaf 100644 --- a/src/vendor/symfony/translation/Resources/data/parents.json +++ b/src/vendor/symfony/translation/Resources/data/parents.json @@ -35,7 +35,6 @@ "en_GM": "en_001", "en_GY": "en_001", "en_HK": "en_001", - "en_ID": "en_001", "en_IE": "en_001", "en_IL": "en_001", "en_IM": "en_001", diff --git a/src/vendor/symfony/translation/Resources/functions.php b/src/vendor/symfony/translation/Resources/functions.php index 0d2a037a2..901d2f87e 100644 --- a/src/vendor/symfony/translation/Resources/functions.php +++ b/src/vendor/symfony/translation/Resources/functions.php @@ -15,7 +15,7 @@ if (!\function_exists(t::class)) { /** * @author Nate Wiebe */ - function t(string $message, array $parameters = [], ?string $domain = null): TranslatableMessage + function t(string $message, array $parameters = [], string $domain = null): TranslatableMessage { return new TranslatableMessage($message, $parameters, $domain); } diff --git a/src/vendor/symfony/translation/Test/ProviderFactoryTestCase.php b/src/vendor/symfony/translation/Test/ProviderFactoryTestCase.php index b8438149d..6d5f4b7bf 100644 --- a/src/vendor/symfony/translation/Test/ProviderFactoryTestCase.php +++ b/src/vendor/symfony/translation/Test/ProviderFactoryTestCase.php @@ -42,17 +42,17 @@ abstract class ProviderFactoryTestCase extends TestCase /** * @return iterable */ - abstract public static function supportsProvider(): iterable; + abstract public function supportsProvider(): iterable; /** - * @return iterable + * @return iterable */ - abstract public static function createProvider(): iterable; + abstract public function createProvider(): iterable; /** * @return iterable */ - public static function unsupportedSchemeProvider(): iterable + public function unsupportedSchemeProvider(): iterable { return []; } @@ -60,7 +60,7 @@ abstract class ProviderFactoryTestCase extends TestCase /** * @return iterable */ - public static function incompleteDsnProvider(): iterable + public function incompleteDsnProvider(): iterable { return []; } @@ -89,7 +89,7 @@ abstract class ProviderFactoryTestCase extends TestCase /** * @dataProvider unsupportedSchemeProvider */ - public function testUnsupportedSchemeException(string $dsn, ?string $message = null) + public function testUnsupportedSchemeException(string $dsn, string $message = null) { $factory = $this->createFactory(); @@ -106,7 +106,7 @@ abstract class ProviderFactoryTestCase extends TestCase /** * @dataProvider incompleteDsnProvider */ - public function testIncompleteDsnException(string $dsn, ?string $message = null) + public function testIncompleteDsnException(string $dsn, string $message = null) { $factory = $this->createFactory(); diff --git a/src/vendor/symfony/translation/Test/ProviderTestCase.php b/src/vendor/symfony/translation/Test/ProviderTestCase.php index cb8a03fc3..4eb08604b 100644 --- a/src/vendor/symfony/translation/Test/ProviderTestCase.php +++ b/src/vendor/symfony/translation/Test/ProviderTestCase.php @@ -34,12 +34,12 @@ abstract class ProviderTestCase extends TestCase protected $loader; protected $xliffFileDumper; - abstract public static function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface; + abstract public function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface; /** - * @return iterable + * @return iterable */ - abstract public static function toStringProvider(): iterable; + abstract public function toStringProvider(): iterable; /** * @dataProvider toStringProvider diff --git a/src/vendor/symfony/translation/TranslatableMessage.php b/src/vendor/symfony/translation/TranslatableMessage.php index 4e53d6079..282d289c0 100644 --- a/src/vendor/symfony/translation/TranslatableMessage.php +++ b/src/vendor/symfony/translation/TranslatableMessage.php @@ -23,7 +23,7 @@ class TranslatableMessage implements TranslatableInterface private $parameters; private $domain; - public function __construct(string $message, array $parameters = [], ?string $domain = null) + public function __construct(string $message, array $parameters = [], string $domain = null) { $this->message = $message; $this->parameters = $parameters; @@ -50,7 +50,7 @@ class TranslatableMessage implements TranslatableInterface return $this->domain; } - public function trans(TranslatorInterface $translator, ?string $locale = null): string + public function trans(TranslatorInterface $translator, string $locale = null): string { return $translator->trans($this->getMessage(), array_map( static function ($parameter) use ($translator, $locale) { diff --git a/src/vendor/symfony/translation/Translator.php b/src/vendor/symfony/translation/Translator.php index 9270e51dc..dc0626093 100644 --- a/src/vendor/symfony/translation/Translator.php +++ b/src/vendor/symfony/translation/Translator.php @@ -89,7 +89,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA /** * @throws InvalidArgumentException If a locale contains invalid characters */ - public function __construct(string $locale, ?MessageFormatterInterface $formatter = null, ?string $cacheDir = null, bool $debug = false, array $cacheVary = []) + public function __construct(string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false, array $cacheVary = []) { $this->setLocale($locale); @@ -127,7 +127,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA * * @throws InvalidArgumentException If the locale contains invalid characters */ - public function addResource(string $format, $resource, string $locale, ?string $domain = null) + public function addResource(string $format, $resource, string $locale, string $domain = null) { if (null === $domain) { $domain = 'messages'; @@ -194,7 +194,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA /** * {@inheritdoc} */ - public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null) + public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null) { if (null === $id || '' === $id) { return ''; @@ -229,7 +229,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA /** * {@inheritdoc} */ - public function getCatalogue(?string $locale = null) + public function getCatalogue(string $locale = null) { if (!$locale) { $locale = $this->getLocale(); diff --git a/src/vendor/symfony/translation/TranslatorBag.php b/src/vendor/symfony/translation/TranslatorBag.php index c8ae1a2fa..555a9e814 100644 --- a/src/vendor/symfony/translation/TranslatorBag.php +++ b/src/vendor/symfony/translation/TranslatorBag.php @@ -38,7 +38,7 @@ final class TranslatorBag implements TranslatorBagInterface /** * {@inheritdoc} */ - public function getCatalogue(?string $locale = null): MessageCatalogueInterface + public function getCatalogue(string $locale = null): MessageCatalogueInterface { if (null === $locale || !isset($this->catalogues[$locale])) { $this->catalogues[$locale] = new MessageCatalogue($locale); @@ -70,7 +70,7 @@ final class TranslatorBag implements TranslatorBagInterface $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH); $newCatalogue = new MessageCatalogue($locale); - foreach ($catalogue->getDomains() as $domain) { + foreach ($operation->getDomains() as $domain) { $newCatalogue->add($operation->getNewMessages($domain), $domain); } diff --git a/src/vendor/symfony/translation/TranslatorBagInterface.php b/src/vendor/symfony/translation/TranslatorBagInterface.php index 3fc3bda39..422897735 100644 --- a/src/vendor/symfony/translation/TranslatorBagInterface.php +++ b/src/vendor/symfony/translation/TranslatorBagInterface.php @@ -31,5 +31,5 @@ interface TranslatorBagInterface * * @throws InvalidArgumentException If the locale contains invalid characters */ - public function getCatalogue(?string $locale = null); + public function getCatalogue(string $locale = null); } diff --git a/src/vendor/symfony/translation/Util/ArrayConverter.php b/src/vendor/symfony/translation/Util/ArrayConverter.php index cbab0c590..f69c2e3c6 100644 --- a/src/vendor/symfony/translation/Util/ArrayConverter.php +++ b/src/vendor/symfony/translation/Util/ArrayConverter.php @@ -38,7 +38,7 @@ class ArrayConverter $tree = []; foreach ($messages as $id => $value) { - $referenceToElement = &self::getElementByPath($tree, self::getKeyParts($id)); + $referenceToElement = &self::getElementByPath($tree, explode('.', $id)); $referenceToElement = $value; @@ -65,7 +65,6 @@ class ArrayConverter $elem = &$elem[implode('.', \array_slice($parts, $i))]; break; } - $parentOfElem = &$elem; $elem = &$elem[$part]; } @@ -97,48 +96,4 @@ class ArrayConverter } } } - - /** - * @return string[] - */ - private static function getKeyParts(string $key): array - { - $parts = explode('.', $key); - $partsCount = \count($parts); - - $result = []; - $buffer = ''; - - foreach ($parts as $index => $part) { - if (0 === $index && '' === $part) { - $buffer = '.'; - - continue; - } - - if ($index === $partsCount - 1 && '' === $part) { - $buffer .= '.'; - $result[] = $buffer; - - continue; - } - - if (isset($parts[$index + 1]) && '' === $parts[$index + 1]) { - $buffer .= $part; - - continue; - } - - if ($buffer) { - $result[] = $buffer.$part; - $buffer = ''; - - continue; - } - - $result[] = $part; - } - - return $result; - } } diff --git a/src/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/src/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php index 379a76517..4cebe44b0 100644 --- a/src/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php +++ b/src/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php @@ -13,7 +13,7 @@ namespace Symfony\Component\VarExporter\Exception; class ClassNotFoundException extends \Exception implements ExceptionInterface { - public function __construct(string $class, ?\Throwable $previous = null) + public function __construct(string $class, \Throwable $previous = null) { parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous); } diff --git a/src/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/src/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php index b9ba225d8..771ee612d 100644 --- a/src/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php +++ b/src/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php @@ -13,7 +13,7 @@ namespace Symfony\Component\VarExporter\Exception; class NotInstantiableTypeException extends \Exception implements ExceptionInterface { - public function __construct(string $type, ?\Throwable $previous = null) + public function __construct(string $type, \Throwable $previous = null) { parent::__construct(sprintf('Type "%s" is not instantiable.', $type), 0, $previous); } diff --git a/src/vendor/symfony/var-exporter/Instantiator.php b/src/vendor/symfony/var-exporter/Instantiator.php index 368c769ac..9e33ea7d4 100644 --- a/src/vendor/symfony/var-exporter/Instantiator.php +++ b/src/vendor/symfony/var-exporter/Instantiator.php @@ -39,10 +39,10 @@ final class Instantiator * Bar::class => ['privateBarProperty' => $propertyValue], * ]); * - * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be created + * Instances of ArrayObject, ArrayIterator and SplObjectHash can be created * by using the special "\0" property name to define their internal value: * - * // creates an SplObjectStorage where $info1 is attached to $obj1, etc. + * // creates an SplObjectHash where $info1 is attached to $obj1, etc. * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); * * // creates an ArrayObject populated with $inputArray diff --git a/src/vendor/symfony/var-exporter/Internal/Exporter.php b/src/vendor/symfony/var-exporter/Internal/Exporter.php index 51c29e45f..cf5283870 100644 --- a/src/vendor/symfony/var-exporter/Internal/Exporter.php +++ b/src/vendor/symfony/var-exporter/Internal/Exporter.php @@ -73,29 +73,20 @@ class Exporter $class = \get_class($value); $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); - $properties = []; if ($reflector->hasMethod('__serialize')) { if (!$reflector->getMethod('__serialize')->isPublic()) { throw new \Error(sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); } - if (!\is_array($serializeProperties = $value->__serialize())) { + if (!\is_array($properties = $value->__serialize())) { throw new \TypeError($class.'::__serialize() must return an array'); } - if ($reflector->hasMethod('__unserialize')) { - $properties = $serializeProperties; - } else { - foreach ($serializeProperties as $n => $v) { - $c = \PHP_VERSION_ID >= 80100 && $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; - $properties[$c][$n] = $v; - } - } - goto prepare_value; } + $properties = []; $sleep = null; $proto = Registry::$prototypes[$class]; @@ -117,7 +108,12 @@ class Exporter $arrayValue = (array) $value; } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class - || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod + || $value instanceof \DatePeriod + || (\PHP_VERSION_ID >= 80200 && ( + $value instanceof \DateTimeInterface + || $value instanceof \DateTimeZone + || $value instanceof \DateInterval + )) ) { ++$objectsCount; $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; @@ -157,11 +153,10 @@ class Exporter $n = substr($n, 1 + $i); } if (null !== $sleep) { - if (!isset($sleep[$name]) && (!isset($sleep[$n]) || ($i && $c !== $class))) { - unset($arrayValue[$name]); + if (!isset($sleep[$n]) || ($i && $c !== $class)) { continue; } - unset($sleep[$name], $sleep[$n]); + $sleep[$n] = false; } if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { $properties[$c][$n] = $v; @@ -169,12 +164,11 @@ class Exporter } if ($sleep) { foreach ($sleep as $n => $v) { - trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); + if (false !== $v) { + trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); + } } } - if (method_exists($class, '__unserialize')) { - $properties = $arrayValue; - } prepare_value: $objectsPool[$value] = [$id = \count($objectsPool)]; @@ -205,7 +199,7 @@ class Exporter case true === $value: return 'true'; case null === $value: return 'null'; case '' === $value: return "''"; - case $value instanceof \UnitEnum: return '\\'.ltrim(var_export($value, true), '\\'); + case $value instanceof \UnitEnum: return ltrim(var_export($value, true), '\\'); } if ($value instanceof Reference) { diff --git a/src/vendor/symfony/var-exporter/LICENSE b/src/vendor/symfony/var-exporter/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/src/vendor/symfony/var-exporter/LICENSE +++ b/src/vendor/symfony/var-exporter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vendor/symfony/var-exporter/VarExporter.php b/src/vendor/symfony/var-exporter/VarExporter.php index d4c080915..003388e79 100644 --- a/src/vendor/symfony/var-exporter/VarExporter.php +++ b/src/vendor/symfony/var-exporter/VarExporter.php @@ -34,11 +34,11 @@ final class VarExporter * * @param mixed $value The value to export * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * @param array &$foundClasses Classes found in the value are added to this list as both keys and values + * @param bool &$classes Classes found in the value are added to this list as both keys and values * * @throws ExceptionInterface When the provided value cannot be serialized */ - public static function export($value, ?bool &$isStaticValue = null, array &$foundClasses = []): string + public static function export($value, bool &$isStaticValue = null, array &$foundClasses = []): string { $isStaticValue = true; @@ -83,7 +83,7 @@ final class VarExporter ksort($states); $wakeups = [null]; - foreach ($states as $v) { + foreach ($states as $k => $v) { if (\is_array($v)) { $wakeups[-$v[0]] = $v[1]; } else { diff --git a/src/vendor/webmozart/assert/CHANGELOG.md b/src/vendor/webmozart/assert/CHANGELOG.md index 560c3b7c3..56c8011de 100644 --- a/src/vendor/webmozart/assert/CHANGELOG.md +++ b/src/vendor/webmozart/assert/CHANGELOG.md @@ -3,18 +3,11 @@ Changelog ## UNRELEASED -### Fixed - -- Corrected messages and typos in various assertions. -- Document `void` return type. -- Prevent UUIDs with trailing newlines from validating. -- Assert values are strings before ctype checks. - ## 1.11.0 ### Added -* Added explicit (non-magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support. +* Added explicit (non magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support. ### Changed @@ -24,7 +17,7 @@ Changelog ### Removed -* Removed `symfony/polyfill-ctype` as a dependency, and require `ext-ctype` instead. +* Removed `symfony/polyfill-ctype` as a dependency, and require `ext-cytpe` instead. * You can still require the `symfony/polyfill-ctype` in your project if you need it, as it provides `ext-ctype` ## 1.10.0 @@ -58,7 +51,7 @@ Changelog ## Changed * the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations. -This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDEs have supported this +This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDE's have supported this for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that. If you do not use PHPStan than this does not matter. diff --git a/src/vendor/webmozart/assert/README.md b/src/vendor/webmozart/assert/README.md index 766099cbd..3b2397a1a 100644 --- a/src/vendor/webmozart/assert/README.md +++ b/src/vendor/webmozart/assert/README.md @@ -91,7 +91,7 @@ Method | Description `positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer `float($value, $message = '')` | Check that a value is a float `numeric($value, $message = '')` | Check that a value is numeric -`natural($value, $message = '')` | Check that a value is a non-negative integer +`natural($value, $message= ''')` | Check that a value is a non-negative integer `boolean($value, $message = '')` | Check that a value is a boolean `scalar($value, $message = '')` | Check that a value is a scalar `object($value, $message = '')` | Check that a value is an object @@ -223,7 +223,7 @@ Assert::allIsInstanceOf($employees, 'Acme\Employee'); ### Nullable Assertions All of the above assertions can be prefixed with `nullOr*()` to run the -assertion only if the value is not `null`: +assertion only if it the value is not `null`: ```php Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s'); @@ -243,7 +243,7 @@ Overriding the following methods in your assertion class allows you to change th * `protected static function valueToString($value)` * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example. * `protected static function typeToString($value)` - * This method is used for error messages, to convert a value to a string representing its type. + * This method is used for error messages, to convert the a value to a string representing its type. * `protected static function strlen($value)` * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful. * `protected static function reportInvalidArgument($message)` diff --git a/src/vendor/webmozart/assert/composer.json b/src/vendor/webmozart/assert/composer.json index dcaf97a2a..b340452c7 100644 --- a/src/vendor/webmozart/assert/composer.json +++ b/src/vendor/webmozart/assert/composer.json @@ -15,14 +15,14 @@ ], "require": { "php": "^7.2 || ^8.0", - "ext-ctype": "*", - "ext-date": "*", - "ext-filter": "*" + "ext-ctype": "*" }, - "suggest": { - "ext-intl": "", - "ext-simplexml": "", - "ext-spl": "" + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "autoload": { "psr-4": { @@ -31,26 +31,13 @@ }, "autoload-dev": { "psr-4": { - "Webmozart\\Assert\\Bin\\": "bin/src", - "Webmozart\\Assert\\Tests\\": "tests/" + "Webmozart\\Assert\\Tests\\": "tests/", + "Webmozart\\Assert\\Bin\\": "bin/src" } }, "extra": { "branch-alias": { "dev-master": "1.10-dev" } - }, - "scripts": { - "install-tools": [ - "composer --working-dir=tools/php-cs-fixer install", - "composer --working-dir=tools/phpunit install", - "composer --working-dir=tools/psalm install", - "composer --working-dir=tools/roave-bc-check install" - ], - "bc-check": "./tools/roave-bc-check/vendor/bin/roave-backward-compatibility-check", - "cs-check" : "./tools/php-cs-fixer/vendor/bin/php-cs-fixer check", - "cs-fix": "./tools/php-cs-fixer/vendor/bin/php-cs-fixer fix", - "static-analysis": "./tools/psalm/vendor/bin/psalm --threads=4 --root=$(pwd)", - "test": "./tools/phpunit/vendor/bin/phpunit" } } diff --git a/src/vendor/webmozart/assert/src/Assert.php b/src/vendor/webmozart/assert/src/Assert.php index 5bf5cfa6e..db1f3a51a 100644 --- a/src/vendor/webmozart/assert/src/Assert.php +++ b/src/vendor/webmozart/assert/src/Assert.php @@ -36,14 +36,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert string $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function string($value, $message = '') @@ -58,14 +55,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert non-empty-string $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function stringNotEmpty($value, $message = '') @@ -76,14 +70,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert int $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function integer($value, $message = '') @@ -98,14 +89,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert numeric $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function integerish($value, $message = '') @@ -120,14 +108,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert positive-int $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function positiveInteger($value, $message = '') @@ -142,14 +127,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert float $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function float($value, $message = '') @@ -164,14 +146,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert numeric $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function numeric($value, $message = '') @@ -186,14 +165,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert positive-int|0 $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function natural($value, $message = '') @@ -208,14 +184,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert bool $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function boolean($value, $message = '') @@ -230,14 +203,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert scalar $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function scalar($value, $message = '') @@ -252,14 +222,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert object $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function object($value, $message = '') @@ -274,15 +241,12 @@ class Assert /** * @psalm-pure - * * @psalm-assert resource $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function resource($value, $type = null, $message = '') @@ -290,8 +254,7 @@ class Assert if (!\is_resource($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a resource. Got: %s', - static::typeToString($value), - $type // User supplied message might include the second placeholder. + static::typeToString($value) )); } @@ -306,14 +269,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert callable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isCallable($value, $message = '') @@ -328,14 +288,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert array $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isArray($value, $message = '') @@ -350,7 +307,6 @@ class Assert /** * @psalm-pure - * * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead @@ -358,8 +314,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isTraversable($value, $message = '') @@ -382,14 +336,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert array|ArrayAccess $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isArrayAccessible($value, $message = '') @@ -404,14 +355,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert countable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isCountable($value, $message = '') @@ -431,14 +379,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isIterable($value, $message = '') @@ -453,19 +398,14 @@ class Assert /** * @psalm-pure - * * @psalm-template ExpectedType of object - * * @psalm-param class-string $class - * * @psalm-assert ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isInstanceOf($value, $class, $message = '') @@ -481,19 +421,14 @@ class Assert /** * @psalm-pure - * * @psalm-template ExpectedType of object - * * @psalm-param class-string $class - * * @psalm-assert !ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notInstanceOf($value, $class, $message = '') @@ -509,15 +444,12 @@ class Assert /** * @psalm-pure - * * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isInstanceOfAny($value, array $classes, $message = '') @@ -537,19 +469,14 @@ class Assert /** * @psalm-pure - * * @psalm-template ExpectedType of object - * * @psalm-param class-string $class - * * @psalm-assert ExpectedType|class-string $value * * @param object|string $value * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isAOf($value, $class, $message = '') @@ -567,11 +494,8 @@ class Assert /** * @psalm-pure - * * @psalm-template UnexpectedType of object - * * @psalm-param class-string $class - * * @psalm-assert !UnexpectedType $value * @psalm-assert !class-string $value * @@ -579,8 +503,6 @@ class Assert * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isNotA($value, $class, $message = '') @@ -598,15 +520,12 @@ class Assert /** * @psalm-pure - * * @psalm-param array $classes * * @param object|string $value * @param string[] $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isAnyOf($value, array $classes, $message = '') @@ -628,14 +547,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert empty $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isEmpty($value, $message = '') @@ -650,14 +566,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert !empty $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notEmpty($value, $message = '') @@ -672,14 +585,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function null($value, $message = '') @@ -694,14 +604,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert !null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notNull($value, $message = '') @@ -715,14 +622,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert true $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function true($value, $message = '') @@ -737,14 +641,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert false $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function false($value, $message = '') @@ -759,14 +660,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert !false $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notFalse($value, $message = '') @@ -782,8 +680,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function ip($value, $message = '') @@ -800,8 +696,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function ipv4($value, $message = '') @@ -818,8 +712,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function ipv6($value, $message = '') @@ -836,8 +728,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function email($value, $message = '') @@ -856,8 +746,6 @@ class Assert * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function uniqueValues(array $values, $message = '') @@ -871,7 +759,7 @@ class Assert static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array of unique values, but %s of them %s duplicated', $difference, - 1 === $difference ? 'is' : 'are' + (1 === $difference ? 'is' : 'are') )); } } @@ -881,8 +769,6 @@ class Assert * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function eq($value, $expect, $message = '') @@ -901,8 +787,6 @@ class Assert * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notEq($value, $expect, $message = '') @@ -922,8 +806,6 @@ class Assert * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function same($value, $expect, $message = '') @@ -944,8 +826,6 @@ class Assert * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notSame($value, $expect, $message = '') @@ -965,8 +845,6 @@ class Assert * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function greaterThan($value, $limit, $message = '') @@ -987,8 +865,6 @@ class Assert * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function greaterThanEq($value, $limit, $message = '') @@ -1009,8 +885,6 @@ class Assert * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function lessThan($value, $limit, $message = '') @@ -1031,8 +905,6 @@ class Assert * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function lessThanEq($value, $limit, $message = '') @@ -1056,8 +928,6 @@ class Assert * @param mixed $max * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function range($value, $min, $max, $message = '') @@ -1081,8 +951,6 @@ class Assert * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function oneOf($value, array $values, $message = '') @@ -1099,8 +967,6 @@ class Assert * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function inArray($value, array $values, $message = '') @@ -1121,8 +987,6 @@ class Assert * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function contains($value, $subString, $message = '') @@ -1143,8 +1007,6 @@ class Assert * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notContains($value, $subString, $message = '') @@ -1164,8 +1026,6 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notWhitespaceOnly($value, $message = '') @@ -1185,8 +1045,6 @@ class Assert * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function startsWith($value, $prefix, $message = '') @@ -1207,8 +1065,6 @@ class Assert * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notStartsWith($value, $prefix, $message = '') @@ -1228,8 +1084,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function startsWithLetter($value, $message = '') @@ -1260,8 +1114,6 @@ class Assert * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function endsWith($value, $suffix, $message = '') @@ -1282,8 +1134,6 @@ class Assert * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notEndsWith($value, $suffix, $message = '') @@ -1304,8 +1154,6 @@ class Assert * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function regex($value, $pattern, $message = '') @@ -1325,8 +1173,6 @@ class Assert * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function notRegex($value, $pattern, $message = '') @@ -1347,8 +1193,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function unicodeLetters($value, $message = '') @@ -1369,8 +1213,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function alpha($value, $message = '') @@ -1396,14 +1238,10 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function digits($value, $message = '') { - static::string($value); - $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_digit($value); @@ -1423,14 +1261,10 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function alnum($value, $message = '') { - static::string($value); - $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_alnum($value); @@ -1446,20 +1280,15 @@ class Assert /** * @psalm-pure - * * @psalm-assert lowercase-string $value * * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function lower($value, $message = '') { - static::string($value); - $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_lower($value); @@ -1475,20 +1304,15 @@ class Assert /** * @psalm-pure - * * @psalm-assert !lowercase-string $value * * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function upper($value, $message = '') { - static::string($value); - $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_upper($value); @@ -1509,8 +1333,6 @@ class Assert * @param int $length * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function length($value, $length, $message = '') @@ -1533,8 +1355,6 @@ class Assert * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function minLength($value, $min, $message = '') @@ -1557,8 +1377,6 @@ class Assert * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function maxLength($value, $max, $message = '') @@ -1582,8 +1400,6 @@ class Assert * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function lengthBetween($value, $min, $max, $message = '') @@ -1606,15 +1422,15 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function fileExists($value, $message = '') { + static::string($value); + if (!\file_exists($value)) { static::reportInvalidArgument(\sprintf( - $message ?: 'The path %s does not exist.', + $message ?: 'The file %s does not exist.', static::valueToString($value) )); } @@ -1624,12 +1440,12 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function file($value, $message = '') { + static::fileExists($value, $message); + if (!\is_file($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not a file.', @@ -1642,15 +1458,15 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function directory($value, $message = '') { + static::fileExists($value, $message); + if (!\is_dir($value)) { static::reportInvalidArgument(\sprintf( - $message ?: 'The path %s is not a directory.', + $message ?: 'The path %s is no directory.', static::valueToString($value) )); } @@ -1660,8 +1476,6 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function readable($value, $message = '') @@ -1678,8 +1492,6 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function writable($value, $message = '') @@ -1698,8 +1510,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function classExists($value, $message = '') @@ -1714,19 +1524,14 @@ class Assert /** * @psalm-pure - * * @psalm-template ExpectedType of object - * * @psalm-param class-string $class - * * @psalm-assert class-string|ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function subclassOf($value, $class, $message = '') @@ -1746,8 +1551,6 @@ class Assert * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function interfaceExists($value, $message = '') @@ -1762,19 +1565,14 @@ class Assert /** * @psalm-pure - * * @psalm-template ExpectedType of object - * * @psalm-param class-string $interface - * - * @psalm-assert class-string|ExpectedType $value + * @psalm-assert class-string $value * * @param mixed $value * @param mixed $interface * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function implementsInterface($value, $interface, $message = '') @@ -1790,15 +1588,12 @@ class Assert /** * @psalm-pure - * * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function propertyExists($classOrObject, $property, $message = '') @@ -1813,15 +1608,12 @@ class Assert /** * @psalm-pure - * * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function propertyNotExists($classOrObject, $property, $message = '') @@ -1836,15 +1628,12 @@ class Assert /** * @psalm-pure - * * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function methodExists($classOrObject, $method, $message = '') @@ -1859,15 +1648,12 @@ class Assert /** * @psalm-pure - * * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function methodNotExists($classOrObject, $method, $message = '') @@ -1887,8 +1673,6 @@ class Assert * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function keyExists($array, $key, $message = '') @@ -1908,8 +1692,6 @@ class Assert * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function keyNotExists($array, $key, $message = '') @@ -1926,14 +1708,11 @@ class Assert * Checks if a value is a valid array key (int or string). * * @psalm-pure - * * @psalm-assert array-key $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function validArrayKey($value, $message = '') @@ -1953,8 +1732,6 @@ class Assert * @param int $number * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function count($array, $number, $message = '') @@ -1977,8 +1754,6 @@ class Assert * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function minCount($array, $min, $message = '') @@ -1999,8 +1774,6 @@ class Assert * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function maxCount($array, $max, $message = '') @@ -2022,8 +1795,6 @@ class Assert * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function countBetween($array, $min, $max, $message = '') @@ -2042,14 +1813,11 @@ class Assert /** * @psalm-pure - * * @psalm-assert list $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isList($array, $message = '') @@ -2060,38 +1828,27 @@ class Assert ); } - if (\function_exists('array_is_list')) { - if (!\array_is_list($array)) { + if ($array === \array_values($array)) { + return; + } + + $nextKey = -1; + foreach ($array as $k => $v) { + if ($k !== ++$nextKey) { static::reportInvalidArgument( $message ?: 'Expected list - non-associative array.' ); } - - return; - } - - if (array() === $array) { - return; - } - - $keys = array_keys($array); - if (array_keys($keys) !== $keys) { - static::reportInvalidArgument( - $message ?: 'Expected list - non-associative array.' - ); } } /** * @psalm-pure - * * @psalm-assert non-empty-list $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isNonEmptyList($array, $message = '') @@ -2102,25 +1859,20 @@ class Assert /** * @psalm-pure - * * @psalm-template T - * * @psalm-param mixed|array $array - * * @psalm-assert array $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isMap($array, $message = '') { if ( - !\is_array($array) - || \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') + !\is_array($array) || + \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') ) { static::reportInvalidArgument( $message ?: 'Expected map - associative array with string keys.' @@ -2130,19 +1882,14 @@ class Assert /** * @psalm-pure - * * @psalm-template T - * * @psalm-param mixed|array $array - * * @psalm-assert array $array * @psalm-assert !empty $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function isNonEmptyMap($array, $message = '') @@ -2157,8 +1904,6 @@ class Assert * @param string $value * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function uuid($value, $message = '') @@ -2171,7 +1916,7 @@ class Assert return; } - if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/D', $value)) { + if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Value %s is not a valid UUID.', static::valueToString($value) @@ -2186,8 +1931,6 @@ class Assert * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException */ public static function throws(Closure $expression, $class = 'Exception', $message = '') @@ -2281,10 +2024,6 @@ class Assert return \get_class($value).': '.self::valueToString($value->format('c')); } - if (\function_exists('enum_exists') && \enum_exists(\get_class($value))) { - return \get_class($value).'::'.$value->name; - } - return \get_class($value); } @@ -2300,8 +2039,6 @@ class Assert } /** - * @psalm-pure - * * @param mixed $value * * @return string @@ -2330,7 +2067,6 @@ class Assert * @throws InvalidArgumentException * * @psalm-pure this method is not supposed to perform side-effects - * * @psalm-return never */ protected static function reportInvalidArgument($message) diff --git a/src/vendor/webmozart/assert/src/Mixin.php b/src/vendor/webmozart/assert/src/Mixin.php index fad0d4756..0f0a75e33 100644 --- a/src/vendor/webmozart/assert/src/Mixin.php +++ b/src/vendor/webmozart/assert/src/Mixin.php @@ -8,22 +8,21 @@ use Countable; use Throwable; /** - * This trait provides nullOr*, all* and allNullOr* variants of assertion base methods. + * This trait provides nurllOr*, all* and allNullOr* variants of assertion base methods. * Do not use this trait directly: it will change, and is not designed for reuse. */ trait Mixin { /** * @psalm-pure - * * @psalm-assert string|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrString($value, $message = '') { @@ -32,15 +31,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allString($value, $message = '') { @@ -53,15 +51,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrString($value, $message = '') { @@ -74,15 +71,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert non-empty-string|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrStringNotEmpty($value, $message = '') { @@ -91,15 +87,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allStringNotEmpty($value, $message = '') { @@ -112,15 +107,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrStringNotEmpty($value, $message = '') { @@ -133,15 +127,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert int|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrInteger($value, $message = '') { @@ -150,15 +143,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allInteger($value, $message = '') { @@ -171,15 +163,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrInteger($value, $message = '') { @@ -192,15 +183,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert numeric|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIntegerish($value, $message = '') { @@ -209,15 +199,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIntegerish($value, $message = '') { @@ -230,15 +219,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIntegerish($value, $message = '') { @@ -251,15 +239,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert positive-int|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrPositiveInteger($value, $message = '') { @@ -268,15 +255,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allPositiveInteger($value, $message = '') { @@ -289,15 +275,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrPositiveInteger($value, $message = '') { @@ -310,15 +295,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert float|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrFloat($value, $message = '') { @@ -327,15 +311,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allFloat($value, $message = '') { @@ -348,15 +331,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrFloat($value, $message = '') { @@ -369,15 +351,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert numeric|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNumeric($value, $message = '') { @@ -386,15 +367,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNumeric($value, $message = '') { @@ -407,15 +387,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNumeric($value, $message = '') { @@ -428,15 +407,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert positive-int|0|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNatural($value, $message = '') { @@ -445,15 +423,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNatural($value, $message = '') { @@ -466,15 +443,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNatural($value, $message = '') { @@ -487,15 +463,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert bool|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrBoolean($value, $message = '') { @@ -504,15 +479,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allBoolean($value, $message = '') { @@ -525,15 +499,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrBoolean($value, $message = '') { @@ -546,15 +519,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert scalar|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrScalar($value, $message = '') { @@ -563,15 +535,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allScalar($value, $message = '') { @@ -584,15 +555,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrScalar($value, $message = '') { @@ -605,15 +575,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert object|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrObject($value, $message = '') { @@ -622,15 +591,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allObject($value, $message = '') { @@ -643,15 +611,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrObject($value, $message = '') { @@ -664,16 +631,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert resource|null $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrResource($value, $type = null, $message = '') { @@ -682,16 +648,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allResource($value, $type = null, $message = '') { @@ -704,16 +669,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrResource($value, $type = null, $message = '') { @@ -726,15 +690,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert callable|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsCallable($value, $message = '') { @@ -743,15 +706,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsCallable($value, $message = '') { @@ -764,15 +726,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsCallable($value, $message = '') { @@ -785,15 +746,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert array|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsArray($value, $message = '') { @@ -802,15 +762,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsArray($value, $message = '') { @@ -823,15 +782,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsArray($value, $message = '') { @@ -844,7 +802,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable|null $value * * @deprecated use "isIterable" or "isInstanceOf" instead @@ -852,9 +809,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsTraversable($value, $message = '') { @@ -863,7 +820,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead @@ -871,9 +827,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsTraversable($value, $message = '') { @@ -886,7 +842,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead @@ -894,9 +849,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsTraversable($value, $message = '') { @@ -909,15 +864,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert array|ArrayAccess|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsArrayAccessible($value, $message = '') { @@ -926,15 +880,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsArrayAccessible($value, $message = '') { @@ -947,15 +900,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsArrayAccessible($value, $message = '') { @@ -968,15 +920,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert countable|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsCountable($value, $message = '') { @@ -985,15 +936,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsCountable($value, $message = '') { @@ -1006,15 +956,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsCountable($value, $message = '') { @@ -1027,15 +976,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsIterable($value, $message = '') { @@ -1044,15 +992,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsIterable($value, $message = '') { @@ -1065,15 +1012,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsIterable($value, $message = '') { @@ -1086,7 +1032,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|null $value @@ -1095,9 +1040,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsInstanceOf($value, $class, $message = '') { @@ -1106,7 +1051,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value @@ -1115,9 +1059,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsInstanceOf($value, $class, $message = '') { @@ -1130,7 +1074,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value @@ -1139,9 +1082,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsInstanceOf($value, $class, $message = '') { @@ -1154,7 +1097,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @@ -1162,9 +1104,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotInstanceOf($value, $class, $message = '') { @@ -1173,7 +1115,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @@ -1181,9 +1122,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotInstanceOf($value, $class, $message = '') { @@ -1196,7 +1137,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value @@ -1205,9 +1145,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotInstanceOf($value, $class, $message = '') { @@ -1220,16 +1160,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsInstanceOfAny($value, $classes, $message = '') { @@ -1238,16 +1177,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsInstanceOfAny($value, $classes, $message = '') { @@ -1260,16 +1198,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsInstanceOfAny($value, $classes, $message = '') { @@ -1282,7 +1219,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|class-string|null $value @@ -1291,9 +1227,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsAOf($value, $class, $message = '') { @@ -1302,7 +1238,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable> $value @@ -1311,9 +1246,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsAOf($value, $class, $message = '') { @@ -1326,7 +1261,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|null> $value @@ -1335,9 +1269,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsAOf($value, $class, $message = '') { @@ -1350,7 +1284,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @@ -1358,9 +1291,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsNotA($value, $class, $message = '') { @@ -1369,7 +1302,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @@ -1377,9 +1309,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsNotA($value, $class, $message = '') { @@ -1392,7 +1324,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value @@ -1402,9 +1333,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsNotA($value, $class, $message = '') { @@ -1417,16 +1348,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param object|string|null $value * @param string[] $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsAnyOf($value, $classes, $message = '') { @@ -1435,16 +1365,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param iterable $value * @param string[] $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsAnyOf($value, $classes, $message = '') { @@ -1457,16 +1386,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param array $classes * * @param iterable $value * @param string[] $classes * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsAnyOf($value, $classes, $message = '') { @@ -1479,15 +1407,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert empty $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsEmpty($value, $message = '') { @@ -1496,15 +1423,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsEmpty($value, $message = '') { @@ -1517,15 +1443,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsEmpty($value, $message = '') { @@ -1542,9 +1467,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotEmpty($value, $message = '') { @@ -1557,9 +1482,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotEmpty($value, $message = '') { @@ -1572,15 +1497,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotEmpty($value, $message = '') { @@ -1593,15 +1517,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNull($value, $message = '') { @@ -1618,9 +1541,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotNull($value, $message = '') { @@ -1633,15 +1556,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert true|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrTrue($value, $message = '') { @@ -1650,15 +1572,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allTrue($value, $message = '') { @@ -1671,15 +1592,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrTrue($value, $message = '') { @@ -1692,15 +1612,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert false|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrFalse($value, $message = '') { @@ -1709,15 +1628,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allFalse($value, $message = '') { @@ -1730,15 +1648,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrFalse($value, $message = '') { @@ -1755,9 +1672,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotFalse($value, $message = '') { @@ -1770,9 +1687,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotFalse($value, $message = '') { @@ -1785,15 +1702,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotFalse($value, $message = '') { @@ -1808,9 +1724,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIp($value, $message = '') { @@ -1821,9 +1737,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIp($value, $message = '') { @@ -1838,9 +1754,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIp($value, $message = '') { @@ -1855,9 +1771,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIpv4($value, $message = '') { @@ -1868,9 +1784,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIpv4($value, $message = '') { @@ -1885,9 +1801,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIpv4($value, $message = '') { @@ -1902,9 +1818,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIpv6($value, $message = '') { @@ -1915,9 +1831,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIpv6($value, $message = '') { @@ -1932,9 +1848,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIpv6($value, $message = '') { @@ -1949,9 +1865,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrEmail($value, $message = '') { @@ -1962,9 +1878,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allEmail($value, $message = '') { @@ -1979,9 +1895,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrEmail($value, $message = '') { @@ -1996,9 +1912,9 @@ trait Mixin * @param array|null $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrUniqueValues($values, $message = '') { @@ -2009,9 +1925,9 @@ trait Mixin * @param iterable $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allUniqueValues($values, $message = '') { @@ -2026,9 +1942,9 @@ trait Mixin * @param iterable $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrUniqueValues($values, $message = '') { @@ -2044,9 +1960,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrEq($value, $expect, $message = '') { @@ -2058,9 +1974,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allEq($value, $expect, $message = '') { @@ -2076,9 +1992,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrEq($value, $expect, $message = '') { @@ -2094,9 +2010,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotEq($value, $expect, $message = '') { @@ -2108,9 +2024,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotEq($value, $expect, $message = '') { @@ -2126,9 +2042,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotEq($value, $expect, $message = '') { @@ -2146,9 +2062,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrSame($value, $expect, $message = '') { @@ -2162,9 +2078,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allSame($value, $expect, $message = '') { @@ -2182,9 +2098,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrSame($value, $expect, $message = '') { @@ -2202,9 +2118,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotSame($value, $expect, $message = '') { @@ -2218,9 +2134,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotSame($value, $expect, $message = '') { @@ -2238,9 +2154,9 @@ trait Mixin * @param mixed $expect * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotSame($value, $expect, $message = '') { @@ -2258,9 +2174,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrGreaterThan($value, $limit, $message = '') { @@ -2274,9 +2190,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allGreaterThan($value, $limit, $message = '') { @@ -2294,9 +2210,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrGreaterThan($value, $limit, $message = '') { @@ -2314,9 +2230,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrGreaterThanEq($value, $limit, $message = '') { @@ -2330,9 +2246,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allGreaterThanEq($value, $limit, $message = '') { @@ -2350,9 +2266,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrGreaterThanEq($value, $limit, $message = '') { @@ -2370,9 +2286,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrLessThan($value, $limit, $message = '') { @@ -2386,9 +2302,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allLessThan($value, $limit, $message = '') { @@ -2406,9 +2322,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrLessThan($value, $limit, $message = '') { @@ -2426,9 +2342,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrLessThanEq($value, $limit, $message = '') { @@ -2442,9 +2358,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allLessThanEq($value, $limit, $message = '') { @@ -2462,9 +2378,9 @@ trait Mixin * @param mixed $limit * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrLessThanEq($value, $limit, $message = '') { @@ -2483,9 +2399,9 @@ trait Mixin * @param mixed $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrRange($value, $min, $max, $message = '') { @@ -2500,9 +2416,9 @@ trait Mixin * @param mixed $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allRange($value, $min, $max, $message = '') { @@ -2521,9 +2437,9 @@ trait Mixin * @param mixed $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrRange($value, $min, $max, $message = '') { @@ -2541,9 +2457,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrOneOf($value, $values, $message = '') { @@ -2557,9 +2473,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allOneOf($value, $values, $message = '') { @@ -2577,9 +2493,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrOneOf($value, $values, $message = '') { @@ -2597,9 +2513,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrInArray($value, $values, $message = '') { @@ -2613,9 +2529,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allInArray($value, $values, $message = '') { @@ -2633,9 +2549,9 @@ trait Mixin * @param array $values * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrInArray($value, $values, $message = '') { @@ -2653,9 +2569,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrContains($value, $subString, $message = '') { @@ -2669,9 +2585,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allContains($value, $subString, $message = '') { @@ -2689,9 +2605,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrContains($value, $subString, $message = '') { @@ -2709,9 +2625,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotContains($value, $subString, $message = '') { @@ -2725,9 +2641,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotContains($value, $subString, $message = '') { @@ -2745,9 +2661,9 @@ trait Mixin * @param string $subString * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotContains($value, $subString, $message = '') { @@ -2764,9 +2680,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotWhitespaceOnly($value, $message = '') { @@ -2779,9 +2695,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotWhitespaceOnly($value, $message = '') { @@ -2798,9 +2714,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotWhitespaceOnly($value, $message = '') { @@ -2818,9 +2734,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrStartsWith($value, $prefix, $message = '') { @@ -2834,9 +2750,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allStartsWith($value, $prefix, $message = '') { @@ -2854,9 +2770,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrStartsWith($value, $prefix, $message = '') { @@ -2874,9 +2790,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotStartsWith($value, $prefix, $message = '') { @@ -2890,9 +2806,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotStartsWith($value, $prefix, $message = '') { @@ -2910,9 +2826,9 @@ trait Mixin * @param string $prefix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotStartsWith($value, $prefix, $message = '') { @@ -2929,9 +2845,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrStartsWithLetter($value, $message = '') { @@ -2944,9 +2860,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allStartsWithLetter($value, $message = '') { @@ -2963,9 +2879,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrStartsWithLetter($value, $message = '') { @@ -2983,9 +2899,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrEndsWith($value, $suffix, $message = '') { @@ -2999,9 +2915,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allEndsWith($value, $suffix, $message = '') { @@ -3019,9 +2935,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrEndsWith($value, $suffix, $message = '') { @@ -3039,9 +2955,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotEndsWith($value, $suffix, $message = '') { @@ -3055,9 +2971,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotEndsWith($value, $suffix, $message = '') { @@ -3075,9 +2991,9 @@ trait Mixin * @param string $suffix * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotEndsWith($value, $suffix, $message = '') { @@ -3095,9 +3011,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrRegex($value, $pattern, $message = '') { @@ -3111,9 +3027,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allRegex($value, $pattern, $message = '') { @@ -3131,9 +3047,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrRegex($value, $pattern, $message = '') { @@ -3151,9 +3067,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrNotRegex($value, $pattern, $message = '') { @@ -3167,9 +3083,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNotRegex($value, $pattern, $message = '') { @@ -3187,9 +3103,9 @@ trait Mixin * @param string $pattern * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrNotRegex($value, $pattern, $message = '') { @@ -3206,9 +3122,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrUnicodeLetters($value, $message = '') { @@ -3221,9 +3137,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allUnicodeLetters($value, $message = '') { @@ -3240,9 +3156,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrUnicodeLetters($value, $message = '') { @@ -3259,9 +3175,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrAlpha($value, $message = '') { @@ -3274,9 +3190,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allAlpha($value, $message = '') { @@ -3293,9 +3209,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrAlpha($value, $message = '') { @@ -3312,9 +3228,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrDigits($value, $message = '') { @@ -3327,9 +3243,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allDigits($value, $message = '') { @@ -3346,9 +3262,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrDigits($value, $message = '') { @@ -3365,9 +3281,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrAlnum($value, $message = '') { @@ -3380,9 +3296,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allAlnum($value, $message = '') { @@ -3399,9 +3315,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrAlnum($value, $message = '') { @@ -3414,15 +3330,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert lowercase-string|null $value * * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrLower($value, $message = '') { @@ -3431,15 +3346,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allLower($value, $message = '') { @@ -3452,15 +3366,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrLower($value, $message = '') { @@ -3477,9 +3390,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrUpper($value, $message = '') { @@ -3492,9 +3405,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allUpper($value, $message = '') { @@ -3507,15 +3420,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrUpper($value, $message = '') { @@ -3533,9 +3445,9 @@ trait Mixin * @param int $length * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrLength($value, $length, $message = '') { @@ -3549,9 +3461,9 @@ trait Mixin * @param int $length * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allLength($value, $length, $message = '') { @@ -3569,9 +3481,9 @@ trait Mixin * @param int $length * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrLength($value, $length, $message = '') { @@ -3589,9 +3501,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMinLength($value, $min, $message = '') { @@ -3605,9 +3517,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMinLength($value, $min, $message = '') { @@ -3625,9 +3537,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMinLength($value, $min, $message = '') { @@ -3645,9 +3557,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMaxLength($value, $max, $message = '') { @@ -3661,9 +3573,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMaxLength($value, $max, $message = '') { @@ -3681,9 +3593,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMaxLength($value, $max, $message = '') { @@ -3702,9 +3614,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrLengthBetween($value, $min, $max, $message = '') { @@ -3719,9 +3631,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allLengthBetween($value, $min, $max, $message = '') { @@ -3740,9 +3652,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrLengthBetween($value, $min, $max, $message = '') { @@ -3757,9 +3669,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrFileExists($value, $message = '') { @@ -3770,9 +3682,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allFileExists($value, $message = '') { @@ -3787,9 +3699,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrFileExists($value, $message = '') { @@ -3804,9 +3716,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrFile($value, $message = '') { @@ -3817,9 +3729,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allFile($value, $message = '') { @@ -3834,9 +3746,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrFile($value, $message = '') { @@ -3851,9 +3763,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrDirectory($value, $message = '') { @@ -3864,9 +3776,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allDirectory($value, $message = '') { @@ -3881,9 +3793,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrDirectory($value, $message = '') { @@ -3898,9 +3810,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrReadable($value, $message = '') { @@ -3911,9 +3823,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allReadable($value, $message = '') { @@ -3928,9 +3840,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrReadable($value, $message = '') { @@ -3945,9 +3857,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrWritable($value, $message = '') { @@ -3958,9 +3870,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allWritable($value, $message = '') { @@ -3975,9 +3887,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrWritable($value, $message = '') { @@ -3994,9 +3906,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrClassExists($value, $message = '') { @@ -4009,9 +3921,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allClassExists($value, $message = '') { @@ -4028,9 +3940,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrClassExists($value, $message = '') { @@ -4043,7 +3955,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert class-string|ExpectedType|null $value @@ -4052,9 +3963,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrSubclassOf($value, $class, $message = '') { @@ -4063,7 +3974,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|ExpectedType> $value @@ -4072,9 +3982,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allSubclassOf($value, $class, $message = '') { @@ -4087,7 +3997,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|ExpectedType|null> $value @@ -4096,9 +4005,9 @@ trait Mixin * @param string|object $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrSubclassOf($value, $class, $message = '') { @@ -4115,9 +4024,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrInterfaceExists($value, $message = '') { @@ -4130,9 +4039,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allInterfaceExists($value, $message = '') { @@ -4149,9 +4058,9 @@ trait Mixin * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrInterfaceExists($value, $message = '') { @@ -4164,18 +4073,17 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $interface - * @psalm-assert class-string|ExpectedType|null $value + * @psalm-assert class-string|null $value * * @param mixed $value * @param mixed $interface * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrImplementsInterface($value, $interface, $message = '') { @@ -4184,18 +4092,17 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $interface - * @psalm-assert iterable|ExpectedType> $value + * @psalm-assert iterable> $value * * @param mixed $value * @param mixed $interface * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allImplementsInterface($value, $interface, $message = '') { @@ -4208,18 +4115,17 @@ trait Mixin /** * @psalm-pure - * * @psalm-template ExpectedType of object * @psalm-param class-string $interface - * @psalm-assert iterable|ExpectedType|null> $value + * @psalm-assert iterable|null> $value * * @param mixed $value * @param mixed $interface * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrImplementsInterface($value, $interface, $message = '') { @@ -4232,16 +4138,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrPropertyExists($classOrObject, $property, $message = '') { @@ -4250,16 +4155,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allPropertyExists($classOrObject, $property, $message = '') { @@ -4272,16 +4176,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrPropertyExists($classOrObject, $property, $message = '') { @@ -4294,16 +4197,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrPropertyNotExists($classOrObject, $property, $message = '') { @@ -4312,16 +4214,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allPropertyNotExists($classOrObject, $property, $message = '') { @@ -4334,16 +4235,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '') { @@ -4356,16 +4256,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMethodExists($classOrObject, $method, $message = '') { @@ -4374,16 +4273,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMethodExists($classOrObject, $method, $message = '') { @@ -4396,16 +4294,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMethodExists($classOrObject, $method, $message = '') { @@ -4418,16 +4315,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMethodNotExists($classOrObject, $method, $message = '') { @@ -4436,16 +4332,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMethodNotExists($classOrObject, $method, $message = '') { @@ -4458,16 +4353,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMethodNotExists($classOrObject, $method, $message = '') { @@ -4485,9 +4379,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrKeyExists($array, $key, $message = '') { @@ -4501,9 +4395,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allKeyExists($array, $key, $message = '') { @@ -4521,9 +4415,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrKeyExists($array, $key, $message = '') { @@ -4541,9 +4435,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrKeyNotExists($array, $key, $message = '') { @@ -4557,9 +4451,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allKeyNotExists($array, $key, $message = '') { @@ -4577,9 +4471,9 @@ trait Mixin * @param string|int $key * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrKeyNotExists($array, $key, $message = '') { @@ -4592,15 +4486,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert array-key|null $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrValidArrayKey($value, $message = '') { @@ -4609,15 +4502,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allValidArrayKey($value, $message = '') { @@ -4630,15 +4522,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $value * * @param mixed $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrValidArrayKey($value, $message = '') { @@ -4654,9 +4545,9 @@ trait Mixin * @param int $number * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrCount($array, $number, $message = '') { @@ -4668,9 +4559,9 @@ trait Mixin * @param int $number * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allCount($array, $number, $message = '') { @@ -4686,9 +4577,9 @@ trait Mixin * @param int $number * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrCount($array, $number, $message = '') { @@ -4704,9 +4595,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMinCount($array, $min, $message = '') { @@ -4718,9 +4609,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMinCount($array, $min, $message = '') { @@ -4736,9 +4627,9 @@ trait Mixin * @param int|float $min * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMinCount($array, $min, $message = '') { @@ -4754,9 +4645,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrMaxCount($array, $max, $message = '') { @@ -4768,9 +4659,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allMaxCount($array, $max, $message = '') { @@ -4786,9 +4677,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrMaxCount($array, $max, $message = '') { @@ -4805,9 +4696,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrCountBetween($array, $min, $max, $message = '') { @@ -4820,9 +4711,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allCountBetween($array, $min, $max, $message = '') { @@ -4839,9 +4730,9 @@ trait Mixin * @param int|float $max * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrCountBetween($array, $min, $max, $message = '') { @@ -4854,15 +4745,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert list|null $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsList($array, $message = '') { @@ -4871,15 +4761,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsList($array, $message = '') { @@ -4892,15 +4781,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsList($array, $message = '') { @@ -4913,15 +4801,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert non-empty-list|null $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsNonEmptyList($array, $message = '') { @@ -4930,15 +4817,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsNonEmptyList($array, $message = '') { @@ -4951,15 +4837,14 @@ trait Mixin /** * @psalm-pure - * * @psalm-assert iterable $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsNonEmptyList($array, $message = '') { @@ -4972,7 +4857,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param mixed|array|null $array * @psalm-assert array|null $array @@ -4980,9 +4864,9 @@ trait Mixin * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsMap($array, $message = '') { @@ -4991,7 +4875,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param iterable> $array * @psalm-assert iterable> $array @@ -4999,9 +4882,9 @@ trait Mixin * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsMap($array, $message = '') { @@ -5014,7 +4897,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param iterable|null> $array * @psalm-assert iterable|null> $array @@ -5022,9 +4904,9 @@ trait Mixin * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsMap($array, $message = '') { @@ -5037,16 +4919,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param mixed|array|null $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrIsNonEmptyMap($array, $message = '') { @@ -5055,16 +4936,15 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param iterable> $array * * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allIsNonEmptyMap($array, $message = '') { @@ -5077,7 +4957,6 @@ trait Mixin /** * @psalm-pure - * * @psalm-template T * @psalm-param iterable|null> $array * @psalm-assert iterable|null> $array @@ -5086,9 +4965,9 @@ trait Mixin * @param mixed $array * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrIsNonEmptyMap($array, $message = '') { @@ -5105,9 +4984,9 @@ trait Mixin * @param string|null $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrUuid($value, $message = '') { @@ -5120,9 +4999,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allUuid($value, $message = '') { @@ -5139,9 +5018,9 @@ trait Mixin * @param iterable $value * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrUuid($value, $message = '') { @@ -5159,9 +5038,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function nullOrThrows($expression, $class = 'Exception', $message = '') { @@ -5175,9 +5054,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allThrows($expression, $class = 'Exception', $message = '') { @@ -5195,9 +5074,9 @@ trait Mixin * @param string $class * @param string $message * - * @return void - * * @throws InvalidArgumentException + * + * @return void */ public static function allNullOrThrows($expression, $class = 'Exception', $message = '') { diff --git a/src/vendor/yunwuxin/think-cron/composer.json b/src/vendor/yunwuxin/think-cron/composer.json index 301e525d6..08a361350 100644 --- a/src/vendor/yunwuxin/think-cron/composer.json +++ b/src/vendor/yunwuxin/think-cron/composer.json @@ -9,9 +9,9 @@ } ], "require": { - "topthink/framework": ">=6.0", + "topthink/framework": "^6.0 || ^8.0", "symfony/process": ">=4.2", - "nesbot/carbon": ">=2.28", + "nesbot/carbon": "^2.28", "dragonmantank/cron-expression": "^3.0" }, "autoload": { diff --git a/src/vendor/yunwuxin/think-cron/src/cron/command/Schedule.php b/src/vendor/yunwuxin/think-cron/src/cron/command/Schedule.php index edeea6041..79ff39c20 100644 --- a/src/vendor/yunwuxin/think-cron/src/cron/command/Schedule.php +++ b/src/vendor/yunwuxin/think-cron/src/cron/command/Schedule.php @@ -19,13 +19,13 @@ class Schedule extends Command { if ('\\' == DIRECTORY_SEPARATOR) { - $command = 'start /B "' . PHP_BINARY . '" think cron:run'; + $command = 'start /B "Niushop Schedule" "' . PHP_BINARY . '" think cron:run'; } else { $command = 'nohup "' . PHP_BINARY . '" think cron:run >> /dev/null 2>&1 &'; } $process = Process::fromShellCommandline($command); - + $output->writeln('['.date('Y-m-d H:i:s').'] Schedule:start'); while (true) { $process->run(); sleep(60);