diff --git a/.travis.yml b/.travis.yml index 04ffb652..40a895b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,24 +5,19 @@ sudo: required language: php php: - - 5.4 - - 5.5 - - 5.6 - 7.0 - 7.1 - 7.2 + - 7.3 - nightly - - hhvm-3.21 - - hhvm-nightly matrix: allow_failures: - php: nightly - - php: hhvm-nightly before_install: - sudo apt-get -qq update - - sudo apt-get install -y imagemagick ghostscript + - sudo apt-get install -y imagemagick ghostscript unifont install: - composer install diff --git a/README.md b/README.md index c5bb5c91..4a223ffb 100644 --- a/README.md +++ b/README.md @@ -165,43 +165,27 @@ If you use any other printer with this code, please [let us know](https://github ### Include the library #### Composer -If you are using composer, then add `mike42/escpos-php` as a dependency: -```bash -composer require mike42/escpos-php -``` - -In this case, you would include composer's auto-loader at the top of your source files: - -```php -=5.4.0", - "ext-mbstring": "*" - }, - "suggest": { - "guzzlehttp/guzzle": "Allows the use of the ApiConnector to send print jobs over HTTP.", - "ext-imagick": "Will be used for image printing if present. Required for PDF printing or use of custom fonts.", - "ext-gd": "Used for image printing if present." - }, - "require-dev": { - "phpunit/phpunit": "^4.8", - "squizlabs/php_codesniffer": "^3.2", - "guzzlehttp/guzzle": "^5.3" - }, - "autoload": { - "psr-4": { - "Mike42\\": "src/Mike42" - } - } + "name" : "mike42/escpos-php", + "type" : "library", + "description" : "PHP receipt printer library for use with ESC/POS-compatible thermal and impact printers", + "homepage" : "https://github.com/mike42/escpos-php", + "keywords" : [ + "barcode", + "epson", + "receipt-printer", + "printer", + "escpos" + ], + "license" : "MIT", + "authors" : [{ + "name" : "Michael Billington", + "email" : "michael.billington@gmail.com" + } + ], + "config": { + "platform": { + "php": "7.0.0" + } + }, + "require" : { + "php" : ">=7.0.0", + "ext-json": "*", + "ext-intl": "*", + "ext-zlib": "*", + "mike42/gfx-php" : "^0.6" + }, + "suggest" : { + "ext-imagick" : "Will be used for image printing if present. Required for PDF printing or use of custom fonts.", + "ext-gd" : "Used for image printing if present." + }, + "require-dev" : { + "phpunit/phpunit" : "^6.5", + "squizlabs/php_codesniffer" : "^3.3" + }, + "autoload" : { + "psr-4" : { + "Mike42\\" : "src/Mike42" + } + } } diff --git a/composer.lock b/composer.lock index d46bbc79..cede613c 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,54 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0094775b67f67bc65c1ff4aebb0fd065", - "packages": [], + "content-hash": "f2f0b78cc96127b158affb47f732de44", + "packages": [ + { + "name": "mike42/gfx-php", + "version": "v0.6", + "source": { + "type": "git", + "url": "https://github.com/mike42/gfx-php.git", + "reference": "ed9ded2a9298e4084a9c557ab74a89b71e43dbdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mike42/gfx-php/zipball/ed9ded2a9298e4084a9c557ab74a89b71e43dbdb", + "reference": "ed9ded2a9298e4084a9c557ab74a89b71e43dbdb", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpbench/phpbench": "@dev", + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "^3.3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mike42\\": "src/Mike42" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Michael Billington", + "email": "michael.billington@gmail.com" + } + ], + "description": "The pure PHP graphics library", + "homepage": "https://github.com/mike42/gfx-php", + "time": "2019-10-05T02:44:33+00:00" + } + ], "packages-dev": [ { "name": "doctrine/instantiator", @@ -62,93 +105,183 @@ "time": "2015-06-14T21:17:01+00:00" }, { - "name": "guzzlehttp/guzzle", - "version": "5.3.2", + "name": "myclabs/deep-copy", + "version": "1.7.0", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f9acb4761844317e626a32259205bec1f1bc60d2" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f9acb4761844317e626a32259205bec1f1bc60d2", - "reference": "f9acb4761844317e626a32259205bec1f1bc60d2", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0", - "react/promise": "^2.2" + "php": "^5.6 || ^7.0" }, "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { "psr-4": { - "GuzzleHttp\\": "src/" - } + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-10-19T19:58:43+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2018-01-15T07:18:01+00:00" + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" }, { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", + "name": "phar-io/version", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", "shasum": "" }, "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" + "php": "^5.6 || ^7.0" }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0" + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] }, - "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Ring\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -157,43 +290,57 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20T03:37:09+00:00" + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" }, { - "name": "guzzlehttp/streams", - "version": "3.0.0", + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.2", "source": { "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.x-dev" } }, "autoload": { "psr-4": { - "GuzzleHttp\\Stream\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -202,54 +349,44 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "stream" - ], - "time": "2014-10-12T19:18:40+00:00" + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-09-12T14:27:41+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", + "name": "phpdocumentor/type-resolver", + "version": "0.5.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "cf842904952e64e703800d094cdf34e715a8a3ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/cf842904952e64e703800d094cdf34e715a8a3ae", + "reference": "cf842904952e64e703800d094cdf34e715a8a3ae", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] + "psr-4": { + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -259,45 +396,45 @@ "authors": [ { "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "email": "me@mikevanriel.com" } ], - "time": "2015-02-03T12:10:50+00:00" + "time": "2017-12-30T13:23:38+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1|^2.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -325,43 +462,44 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2019-10-03T11:07:50+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -376,7 +514,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -387,20 +525,20 @@ "testing", "xunit" ], - "time": "2015-10-06T15:47:00+00:00" + "time": "2018-04-06T15:36:58+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -434,7 +572,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -528,29 +666,29 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -573,45 +711,57 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "4.8.36", + "version": "6.5.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.9", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" }, "suggest": { - "phpunit/php-invoker": "~1.1" + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" }, "bin": [ "phpunit" @@ -619,7 +769,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -645,30 +795,33 @@ "testing", "xunit" ], - "time": "2017-06-21T08:07:12+00:00" + "time": "2019-02-01T05:22:47+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "5.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.5.11" }, "suggest": { "ext-soap": "*" @@ -676,7 +829,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -691,7 +844,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -701,80 +854,80 @@ "mock", "xunit" ], - "time": "2015-10-02T06:51:40+00:00" + "abandoned": true, + "time": "2018-08-09T05:50:03+00:00" }, { - "name": "react/promise", - "version": "v2.5.1", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/62785ae604c8d69725d693eb370e1d67e94c4053", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "time": "2017-03-25T12:08:31+00:00" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", - "version": "1.2.4", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -805,38 +958,38 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -863,32 +1016,32 @@ "keywords": [ "diff" ], - "time": "2015-12-08T07:14:41+00:00" + "time": "2017-08-03T08:09:46+00:00" }, { "name": "sebastian/environment", - "version": "1.3.8", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -913,34 +1066,34 @@ "environment", "hhvm" ], - "time": "2016-08-18T05:49:44+00:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -953,6 +1106,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -961,17 +1118,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -980,27 +1133,27 @@ "export", "exporter" ], - "time": "2016-06-17T09:04:28+00:00" + "time": "2019-09-14T09:02:43+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -1008,7 +1161,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1031,32 +1184,124 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.5", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1084,23 +1329,73 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, + "require": { + "php": ">=5.6" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1119,20 +1414,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.2.3", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27" + "reference": "0afebf16a2e7f1e434920fa976253576151effe9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9", + "reference": "0afebf16a2e7f1e434920fa976253576151effe9", "shasum": "" }, "require": { @@ -1165,53 +1460,45 @@ } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", "standards" ], - "time": "2018-02-20T21:35:23+00:00" + "time": "2019-09-26T23:12:26+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v2.8.18", + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bb4ec47e8e109c1c1172145732d0aa468d967cd0", - "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" + "php": ">=5.3.3" }, "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "1.12-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1220,48 +1507,95 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2017-02-21T08:33:48+00:00" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" }, { - "name": "symfony/yaml", - "version": "v2.8.18", + "name": "theseer/tokenizer", + "version": "1.1.3", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d" + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d", - "reference": "2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", "shasum": "" }, "require": { - "php": ">=5.3.9" + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "1.3-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Webmozart\\Assert\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1269,17 +1603,17 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-03-01T18:13:50+00:00" + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-08-24T08:43:50+00:00" } ], "aliases": [], @@ -1288,11 +1622,11 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.4.0", + "php": ">=7.0.0", "ext-mbstring": "*" }, "platform-dev": [], "platform-overrides": { - "php": "5.4.0" + "php": "7.0.0" } } diff --git a/example/barcode.php b/example/barcode.php index d3ef9f2f..339a1ec5 100644 --- a/example/barcode.php +++ b/example/barcode.php @@ -1,5 +1,5 @@ */ -require __DIR__ . '/../autoload.php'; +require __DIR__ . '/../vendor/autoload.php'; use Mike42\Escpos\Printer; use Mike42\Escpos\PrintConnectors\FilePrintConnector; use Mike42\Escpos\EscposImage; diff --git a/example/graphics.php b/example/graphics.php index 49b02b9b..ff7755d4 100644 --- a/example/graphics.php +++ b/example/graphics.php @@ -1,7 +1,7 @@ */ -require __DIR__ . '/../autoload.php'; +require __DIR__ . '/../vendor/autoload.php'; use Mike42\Escpos\Printer; use Mike42\Escpos\PrintConnectors\FilePrintConnector; diff --git a/example/unifont-print-buffer.php b/example/unifont-print-buffer.php new file mode 100644 index 00000000..1b953c29 --- /dev/null +++ b/example/unifont-print-buffer.php @@ -0,0 +1,22 @@ + setPrintBuffer($unifontBuffer); + +// Most simple example +$printer->text("Hello\n"); +$printer->setUpsideDown(true); +$printer->text("World\n"); +$printer->cut(); +$printer->close(); + diff --git a/example/upside-down.php b/example/upside-down.php new file mode 100644 index 00000000..0185ca97 --- /dev/null +++ b/example/upside-down.php @@ -0,0 +1,16 @@ + text("Hello\n"); +$printer -> setUpsideDown(true); +$printer -> text("World\n"); +$printer -> cut(); +$printer -> close(); + diff --git a/src/Mike42/Escpos/CapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfile.php index 9a913905..8b81226b 100644 --- a/src/Mike42/Escpos/CapabilityProfile.php +++ b/src/Mike42/Escpos/CapabilityProfile.php @@ -113,7 +113,7 @@ class CapabilityProfile * @param array $profileData * Profile data from disk. */ - protected function __construct($profileId, array $profileData) + protected function __construct(string $profileId, array $profileData) { // Basic primitive fields $this->profileId = $profileId; @@ -137,16 +137,16 @@ protected function __construct($profileId, array $profileData) * * @return string Hash of the code page data structure, to identify it for caching. */ - public function getCodePageCacheKey() + public function getCodePageCacheKey() : string { return $this->codePageCacheKey; } /** * - * @return array Associtive array of CodePage objects, indicating which encodings the printer supports. + * @return array Associative array of CodePage objects, indicating which encodings the printer supports. */ - public function getCodePages() + public function getCodePages() : array { return $this->codePages; } @@ -174,7 +174,7 @@ public function getFeature($featureName) * * @return string ID of the profile. */ - public function getId() + public function getId() : string { return $this->profileId; } @@ -183,7 +183,7 @@ public function getId() * * @return string Name of the printer. */ - public function getName() + public function getName() : string { return $this->name; } @@ -192,7 +192,7 @@ public function getName() * * @return boolean True if Barcode B command is supported, false otherwise */ - public function getSupportsBarcodeB() + public function getSupportsBarcodeB() : bool { return $this->getFeature('barcodeB') === true; } @@ -201,7 +201,7 @@ public function getSupportsBarcodeB() * * @return boolean True if Bit Image Raster command is supported, false otherwise */ - public function getSupportsBitImageRaster() + public function getSupportsBitImageRaster() : bool { return $this->getFeature('bitImageRaster') === true; } @@ -210,7 +210,7 @@ public function getSupportsBitImageRaster() * * @return boolean True if Graphics command is supported, false otherwise */ - public function getSupportsGraphics() + public function getSupportsGraphics() : bool { return $this->getFeature('graphics') === true; } @@ -219,17 +219,16 @@ public function getSupportsGraphics() * * @return boolean True if PDF417 code command is supported, false otherwise */ - public function getSupportsPdf417Code() + public function getSupportsPdf417Code() : bool { - // TODO submit 'pdf417Code' as a new feature to be tracked in upstream profiles - return $this->getFeature('qrCode') === true; + return $this->getFeature('pdf417Code') === true; } /** * * @return boolean True if QR code command is supported, false otherwise */ - public function getSupportsQrCode() + public function getSupportsQrCode(): bool { return $this->getFeature('qrCode') === true; } @@ -238,7 +237,7 @@ public function getSupportsQrCode() * * @return boolean True if Star mode commands are supported, false otherwise */ - public function getSupportsStarCommands() + public function getSupportsStarCommands(): bool { return $this->getFeature('starCommands') === true; } @@ -247,7 +246,7 @@ public function getSupportsStarCommands() * * @return string Vendor of this printer. */ - public function getVendor() + public function getVendor() : string { return $this->vendor; } @@ -258,7 +257,7 @@ public function getVendor() * Feature that does not exist * @return array Three most similar feature names that do exist. */ - protected function suggestFeatureName($featureName) + protected function suggestFeatureName(string $featureName) : array { return self::suggestNearest($featureName, array_keys($this->features), 3); } @@ -267,7 +266,7 @@ protected function suggestFeatureName($featureName) * * @return array Names of all profiles that exist. */ - public static function getProfileNames() + public static function getProfileNames() : array { self::loadCapabilitiesDataFile(); return array_keys(self::$profiles); @@ -281,7 +280,7 @@ public static function getProfileNames() * @throws InvalidArgumentException Where the ID does not exist. Some similarly-named profiles will be suggested in the Exception text. * @return CapabilityProfile The CapabilityProfile that was requested. */ - public static function load($profileName) + public static function load(string $profileName) { self::loadCapabilitiesDataFile(); if (! isset(self::$profiles[$profileName])) { @@ -315,7 +314,7 @@ protected static function loadCapabilitiesDataFile() * @param int $num * Number of suggestions to return */ - public static function suggestNearest($input, array $choices, $num) + public static function suggestNearest(string $input, array $choices, int $num) : array { $distances = array_fill_keys($choices, PHP_INT_MAX); foreach ($distances as $word => $_) { @@ -331,7 +330,7 @@ public static function suggestNearest($input, array $choices, $num) * profile name that does not exist * @return array Three similar profile names that do exist, plus 'simple' and 'default' for good measure. */ - protected static function suggestProfileName($profileName) + protected static function suggestProfileName(string $profileName) : array { $suggestions = self::suggestNearest($profileName, array_keys(self::$profiles), 3); $alwaysSuggest = [ diff --git a/src/Mike42/Escpos/CapabilityProfiles/DefaultCapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfiles/DefaultCapabilityProfile.php deleted file mode 100644 index c574aed1..00000000 --- a/src/Mike42/Escpos/CapabilityProfiles/DefaultCapabilityProfile.php +++ /dev/null @@ -1,22 +0,0 @@ -, - * incorporating modifications by others. See CONTRIBUTORS.md for a full list. - * - * This software is distributed under the terms of the MIT license. See LICENSE.md - * for details. - */ -namespace Mike42\Escpos\CapabilityProfiles; - -use Mike42\Escpos\CapabilityProfile; - -class DefaultCapabilityProfile -{ - public static function getInstance() - { - return CapabilityProfile::load('default'); - } -} diff --git a/src/Mike42/Escpos/CapabilityProfiles/EposTepCapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfiles/EposTepCapabilityProfile.php deleted file mode 100644 index cc8e3ec5..00000000 --- a/src/Mike42/Escpos/CapabilityProfiles/EposTepCapabilityProfile.php +++ /dev/null @@ -1,22 +0,0 @@ -, - * incorporating modifications by others. See CONTRIBUTORS.md for a full list. - * - * This software is distributed under the terms of the MIT license. See LICENSE.md - * for details. - */ -namespace Mike42\Escpos\CapabilityProfiles; - -use Mike42\Escpos\CapabilityProfile; - -class EposTepCapabilityProfile -{ - public static function getInstance() - { - return CapabilityProfile::load('TEP-200M'); - } -} diff --git a/src/Mike42/Escpos/CapabilityProfiles/P822DCapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfiles/P822DCapabilityProfile.php deleted file mode 100644 index 42ee3a0b..00000000 --- a/src/Mike42/Escpos/CapabilityProfiles/P822DCapabilityProfile.php +++ /dev/null @@ -1,22 +0,0 @@ -, - * incorporating modifications by others. See CONTRIBUTORS.md for a full list. - * - * This software is distributed under the terms of the MIT license. See LICENSE.md - * for details. - */ -namespace Mike42\Escpos\CapabilityProfiles; - -use Mike42\Escpos\CapabilityProfile; - -class P822DCapabilityProfile -{ - public static function getInstance() - { - return CapabilityProfile::load('P822D'); - } -} diff --git a/src/Mike42/Escpos/CapabilityProfiles/SimpleCapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfiles/SimpleCapabilityProfile.php deleted file mode 100644 index cb141b8b..00000000 --- a/src/Mike42/Escpos/CapabilityProfiles/SimpleCapabilityProfile.php +++ /dev/null @@ -1,22 +0,0 @@ -, - * incorporating modifications by others. See CONTRIBUTORS.md for a full list. - * - * This software is distributed under the terms of the MIT license. See LICENSE.md - * for details. - */ -namespace Mike42\Escpos\CapabilityProfiles; - -use Mike42\Escpos\CapabilityProfile; - -class SimpleCapabilityProfile -{ - public static function getInstance() - { - return CapabilityProfile::load('simple'); - } -} diff --git a/src/Mike42/Escpos/CapabilityProfiles/StarCapabilityProfile.php b/src/Mike42/Escpos/CapabilityProfiles/StarCapabilityProfile.php deleted file mode 100644 index 6e2f64c2..00000000 --- a/src/Mike42/Escpos/CapabilityProfiles/StarCapabilityProfile.php +++ /dev/null @@ -1,22 +0,0 @@ -, - * incorporating modifications by others. See CONTRIBUTORS.md for a full list. - * - * This software is distributed under the terms of the MIT license. See LICENSE.md - * for details. - */ -namespace Mike42\Escpos\CapabilityProfiles; - -use Mike42\Escpos\CapabilityProfile; - -class StarCapabilityProfile -{ - public static function getInstance() - { - return CapabilityProfile::load('SP2000'); - } -} diff --git a/src/Mike42/Escpos/CodePage.php b/src/Mike42/Escpos/CodePage.php index 25f58b95..b0bb35ae 100644 --- a/src/Mike42/Escpos/CodePage.php +++ b/src/Mike42/Escpos/CodePage.php @@ -18,23 +18,23 @@ * Class to handle data about a particular CodePage, as loaded from the receipt print * database. * - * Also computes map between UTF-8 and this encoding if necessary, using the iconv library. + * Also computes map between UTF-8 and this encoding if necessary, using the intl library. */ class CodePage { /** - * The input encoding for generating character maps with iconv. + * Value to use when no character is set. This is a space in ASCII. */ - const INPUT_ENCODING = "UTF-8"; + const MISSING_CHAR_CODE = 0x20; /** - * @var string $data + * @var array|null $data * Data string, null if not known (can be computed with iconv) */ protected $data; /** - * @var string $iconv + * @var string|null $iconv * Iconv encoding name, null if not known */ protected $iconv; @@ -52,7 +52,7 @@ class CodePage protected $name; /** - * @var string $notes + * @var string|null $notes * Notes on this code page, or null if not set. */ protected $notes; @@ -70,28 +70,27 @@ public function __construct($id, array $codePageData) { $this->id = $id; $this->name = isset($codePageData['name']) ? $codePageData['name'] : $id; - $this->data = isset($codePageData['data']) ? implode("", $codePageData['data']) : null; + $this->data = isset($codePageData['data']) ? self::encodingArrayFromData($codePageData['data']) : null; $this->iconv = isset($codePageData['iconv']) ? $codePageData['iconv'] : null; $this->notes = isset($codePageData['notes']) ? $codePageData['notes'] : null; } /** - * Get a 128-character data string representing this encoding. - * It will be - * calculated and cached if it was not previously known. + * Get a 128-entry array of unicode code-points from this code page. * * @throws InvalidArgumentException Where the data is now known or computable. - * @return string Data for this encoding. + * @return array Data for this encoding. */ - public function getData() + public function getDataArray() : array { + // Make string if ($this->data !== null) { // Return data if known return $this->data; } if ($this->iconv !== null) { // Calculate with iconv if we know the encoding name - $this->data = self::generateEncodingMap($this->iconv); + $this->data = self::generateEncodingArray($this->iconv); return $this->data; } // Can't encode.. @@ -100,7 +99,7 @@ public function getData() /** * - * @return string Iconv encoding name, or blank if not set. + * @return string|null Iconv encoding name, or null if not set. */ public function getIconv() { @@ -111,15 +110,15 @@ public function getIconv() * * @return string Unique identifier of the code page. */ - public function getId() + public function getId() : string { return $this->id; } /** - * Name of the code page. + * @return string Name of the code page. */ - public function getName() + public function getName() : string { return $this->name; } @@ -127,7 +126,7 @@ public function getName() /** * The notes may explain quirks about a code-page, such as a source if it's non-standard or un-encodeable. * - * @return string Notes on the code page, or null if not set. + * @return string|null Notes on the code page, or null if not set. */ public function getNotes() { @@ -147,35 +146,53 @@ public function isEncodable() } /** - * Given an iconv encoding name, generate a 128-character UTF-8 string, containing code points 128-255. + * Given an ICU encoding name, generate a 128-entry array, with the unicode code points + * for the character at positions 128-255 in this code page. * - * This string is used to map UTF-8 characters to their location in this code page. - * - * @param string $iconvName - * Name of the encoding - * @return string 128-character string in UTF-8. + * @param string $encodingName Name of the encoding + * @return array 128-entry array of code points */ - protected static function generateEncodingMap($iconvName) + protected static function generateEncodingArray(string $encodingName) : array { - // Start with array of blanks (" " indicates unknown character). - $charMap = array_fill(0, 128, " "); + // Set up converter for encoding + $missingChar = chr(self::MISSING_CHAR_CODE); + // Throws a lot of warnings for ambiguous code pages, but fallbacks seem fine. + $converter = @new \UConverter("UTF-8", $encodingName); + $converter -> setSubstChars($missingChar); // Loop through 128 code points - for ($char = 128; $char <= 255; $char ++) { - // Try to identify the UTF-8 character that would go here - $utf8 = @iconv($iconvName, self::INPUT_ENCODING, chr($char)); - if ($utf8 == '') { + $intArray = array_fill(0, 128, self::MISSING_CHAR_CODE); + for ($char = 128; $char <= 255; $char++) { + // Try to identify the UTF-8 character at this position in the code page + $encodingChar = chr($char); + $utf8 = $converter ->convert($encodingChar, false); + if ($utf8 === $missingChar) { + // Cannot be mapped to unicode continue; } - if (iconv(self::INPUT_ENCODING, $iconvName, $utf8) != chr($char)) { - // Avoid non-canonical conversions (no known examples) + $reverse = $converter ->convert($utf8, true); + if ($reverse !== $encodingChar) { + // Avoid conversions which don't reverse well (eg. multi-byte code pages) continue; } - // Replace the ' ' with the correct character if we found it - $charMap[$char - 128] = $utf8; + // Replace space with the correct character if we found it + $intArray[$char - 128] = \IntlChar::ord($utf8); + } + assert(count($intArray) == 128); + return $intArray; + } + + + private static function encodingArrayFromData(array $data) : array + { + $text = implode("", $data); // Join lines + $codePointIterator = \IntlBreakIterator::createCodePointInstance(); + $codePointIterator -> setText($text); + $ret = array_fill(0, 128, self::MISSING_CHAR_CODE); + for ($i = 0; ($codePointIterator -> next() > 0) && ($i < 128); $i++) { + $codePoint = $codePointIterator -> getLastCodePoint(); + $ret[$i] = $codePoint; } - // Join into a 128-character string and return. - $charMapStr = implode("", $charMap); - assert(mb_strlen($charMapStr, self::INPUT_ENCODING) == 128); - return $charMapStr; + assert(count($ret) == 128); + return $ret; } } diff --git a/src/Mike42/Escpos/Devices/AuresCustomerDisplay.php b/src/Mike42/Escpos/Devices/AuresCustomerDisplay.php index 3bf9101a..d5a171c7 100644 --- a/src/Mike42/Escpos/Devices/AuresCustomerDisplay.php +++ b/src/Mike42/Escpos/Devices/AuresCustomerDisplay.php @@ -74,7 +74,7 @@ protected function selectEscposMode() * AuresCustomerDisplay::TEXT_VERTICAL_SCROLL or * AuresCustomerDisplay::TEXT_HORIZONTAL_SCROLL */ - public function selectTextScrollMode($mode = AuresCustomerDisplay::TEXT_VERTICAL_SCROLL) + public function selectTextScrollMode(int $mode = AuresCustomerDisplay::TEXT_VERTICAL_SCROLL) { self::validateInteger($mode, 1, 3, __FUNCTION__); $this->connector->write("\x1F" . chr($mode)); @@ -122,9 +122,8 @@ public function showLogo() * * @see \Mike42\Escpos\Printer::text() */ - public function text($str = "") + public function text(string $str) { - self::validateString($str, __FUNCTION__); // Need to intercept line-feeds, since "\n" is insufficient on this device. foreach (explode("\n", $str) as $id => $line) { if ($id > 0) { @@ -140,7 +139,7 @@ public function text($str = "") * * @see \Mike42\Escpos\Printer::feed() */ - public function feed($lines = 1) + public function feed(int $lines = 1) { self::validateInteger($lines, 1, 255, __FUNCTION__); for ($i = 0; $i < $lines; $i ++) { diff --git a/src/Mike42/Escpos/EscposImage.php b/src/Mike42/Escpos/EscposImage.php index 9a625acb..212874e8 100644 --- a/src/Mike42/Escpos/EscposImage.php +++ b/src/Mike42/Escpos/EscposImage.php @@ -14,6 +14,9 @@ use Exception; use InvalidArgumentException; +use Mike42\Escpos\GdEscposImage; +use Mike42\Escpos\ImagickEscposImage; +use Mike42\Escpos\NativeEscposImage; /** * This class deals with images in raster formats, and converts them into formats @@ -192,7 +195,7 @@ public function toColumnFormat($doubleDensity = false) * * @param string|null $filename Filename to load from. */ - protected function loadImageData($filename = null) + protected function loadImageData(string $filename = null) { // Load image in to string of 1's and 0's, also set width & height $this -> setImgWidth(0); @@ -312,7 +315,7 @@ private function getRasterFormat() * @return string[] * Array of column format data, one item per row. */ - private function getColumnFormat($highDensity) + private function getColumnFormat(bool $highDensity) { $out = []; $i = 0; @@ -335,7 +338,7 @@ private function getColumnFormat($highDensity) * @return NULL|string * Column format data, or null if there is no more data (when iterating) */ - private function getColumnFormatLine($lineNo, $highDensity) + private function getColumnFormatLine(int $lineNo, bool $highDensity) { // Currently double density in both directions, very experimental $widthPixels = $this -> getWidth(); @@ -421,8 +424,8 @@ public static function isImagickLoaded() * */ public static function load( - $filename, - $allowOptimisations = true, + string $filename, + bool $allowOptimisations = true, array $preferred = ['imagick', 'gd', 'native'] ) { /* Fail early if file is not readble */ @@ -431,28 +434,28 @@ public static function load( } $ext = pathinfo($filename, PATHINFO_EXTENSION); /* Choose the first implementation which can handle this format */ - foreach ($preferred as $implemetnation) { - if ($implemetnation === 'imagick') { + foreach ($preferred as $implementation) { + if ($implementation === 'imagick') { if (!self::isImagickLoaded()) { // Skip option if Imagick is not loaded continue; } - return new \Mike42\Escpos\ImagickEscposImage($filename, $allowOptimisations); - } elseif ($implemetnation === 'gd') { + return new ImagickEscposImage($filename, $allowOptimisations); + } elseif ($implementation === 'gd') { if (!self::isGdLoaded()) { // Skip option if GD not loaded continue; } - return new \Mike42\Escpos\GdEscposImage($filename, $allowOptimisations); - } elseif ($implemetnation === 'native') { - if (!in_array($ext, ['wbmp', 'pbm', 'bmp'])) { - // Pure PHP is fastest way to generate raster output from wbmp and pbm formats. + return new GdEscposImage($filename, $allowOptimisations); + } elseif ($implementation === 'native') { + if (!in_array($ext, ['bmp', 'gif', 'pbm', 'png', 'ppm', 'pgm', 'wbmp'])) { + // Pure PHP may also be fastest way to generate raster output from wbmp and pbm formats. continue; } - return new \Mike42\Escpos\NativeEscposImage($filename, $allowOptimisations); + return new NativeEscposImage($filename, $allowOptimisations); } else { // Something else on the 'preferred' list. - throw new InvalidArgumentException("'$implemetnation' is not a known EscposImage implementation"); + throw new InvalidArgumentException("'$implementation' is not a known EscposImage implementation"); } } throw new InvalidArgumentException("No suitable EscposImage implementation found for '$filename'."); diff --git a/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyph.php b/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyph.php new file mode 100644 index 00000000..10ab0ce7 --- /dev/null +++ b/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyph.php @@ -0,0 +1,25 @@ +width <= $maxWidth) { + return [$this]; + } + $dataChunks = str_split($this->data, $maxWidth * 3); + $ret = []; + foreach ($dataChunks as $chunk) { + $g = new ColumnFormatGlyph(); + $g->data = $chunk; + $g->width = strlen($chunk) / 3; + $ret[] = $g; + } + return $ret; + } +} diff --git a/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyphFactory.php b/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyphFactory.php new file mode 100644 index 00000000..01307c46 --- /dev/null +++ b/src/Mike42/Escpos/Experimental/Unifont/ColumnFormatGlyphFactory.php @@ -0,0 +1,8 @@ + printer = $printer; + $this -> glyphFactory = $glyphFactory; + $this -> reset(); + } + + public function cacheChars(array $codePoints) + { + // TODO flush existing cache to fill with these chars. + } + + public function writeChar(int $codePoint) + { + if (!$this -> addChar($codePoint, true)) { + throw new InvalidArgumentException("Code point $codePoint not available"); + } + $data = implode($this -> chars[$codePoint]); + $this -> printer -> getPrintConnector() -> write($data); + } + + public function reset() + { + $this -> chars = []; + $this -> memory = array_fill(0, (\Mike42\Escpos\Experimental\Unifont\FontMap::MAX - FontMap::MIN) + 1, -1); + } + + public function occupied($id) + { + return $this -> memory[$id] !== -1; + } + + public function evict($id) + { + if (!$this -> occupied($id)) { + return true; + } + unset($this -> chars[$this -> memory[$id]]); + $this -> memory[$id] = -1; + return true; + } + + public function addChar(int $codePoint, $evict = true) + { + if (isset($this -> chars[$codePoint])) { + // Char already available + return true; + } + // Get glyph + $glyph = $this -> glyphFactory -> getGlyph($codePoint); + $glyphParts = $glyph -> segment(self::FONT_B_WIDTH); + //print_r($glyphParts); + // + // Clear count($glyphParts) of space from $start + $start = $this -> next; + $chars = []; + $submit = []; + for ($i = 0; $i < count($glyphParts); $i++) { + $id = ($this -> next + $i) % count($this -> memory); + if ($this -> occupied($id)) { + if ($evict) { + $this -> evict($id); + } else { + return false; + } + } + $thisChar = $id + self::MIN; + $chars[] = chr($thisChar); + $submit[$thisChar] = $glyphParts[$i]; + } + + // Success in locating memory space, move along counters + $this -> next = ($this -> next + count($glyphParts)) % count($this -> memory); + $this -> submitCharsToPrinterFont($submit); + $this -> memory[$start] = $codePoint; + $this -> chars[$codePoint] = $chars; + + return true; + } + + public function submitCharsToPrinterFont(array $chars) + { + ksort($chars); + // TODO We can sort into batches of contiguous characters here. + foreach ($chars as $char => $glyph) { + $verticalBytes = 3; + $data = Printer::ESC . "&" . chr($verticalBytes) . chr($char) . chr($char) . chr($glyph -> width) . $glyph -> data; + $this -> printer -> getPrintConnector() -> write($data); + } + } +} diff --git a/src/Mike42/Escpos/Experimental/Unifont/UnifontGlyphFactory.php b/src/Mike42/Escpos/Experimental/Unifont/UnifontGlyphFactory.php new file mode 100644 index 00000000..d6da739d --- /dev/null +++ b/src/Mike42/Escpos/Experimental/Unifont/UnifontGlyphFactory.php @@ -0,0 +1,234 @@ +> 1) | + (($in[2 * $chars + $idx] & 0x80) >> 2) | + (($in[3 * $chars + $idx] & 0x80) >> 3) | + (($in[4 * $chars + $idx] & 0x80) >> 4) | + (($in[5 * $chars + $idx] & 0x80) >> 5) | + (($in[6 * $chars + $idx] & 0x80) >> 6) | + (($in[7 * $chars + $idx] & 0x80) >> 7) + ), + chr( + (($in[8 * $chars + $idx] & 0x80)) | + (($in[9 * $chars + $idx] & 0x80) >> 1) | + (($in[10 * $chars + $idx] & 0x80) >> 2) | + (($in[11 * $chars + $idx] & 0x80) >> 3) | + (($in[12 * $chars + $idx] & 0x80) >> 4) | + (($in[13 * $chars + $idx] & 0x80) >> 5) | + (($in[14 * $chars + $idx] & 0x80) >> 6) | + (($in[15 * $chars + $idx] & 0x80) >> 7) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x40) << 1) | + (($in[1 * $chars + $idx] & 0x40)) | + (($in[2 * $chars + $idx] & 0x40) >> 1) | + (($in[3 * $chars + $idx] & 0x40) >> 2) | + (($in[4 * $chars + $idx] & 0x40) >> 3) | + (($in[5 * $chars + $idx] & 0x40) >> 4) | + (($in[6 * $chars + $idx] & 0x40) >> 5) | + (($in[7 * $chars + $idx] & 0x40) >> 6) + ), + chr( + (($in[8 * $chars + $idx] & 0x40) << 1) | + (($in[9 * $chars + $idx] & 0x40) >> 0) | + (($in[10 * $chars + $idx] & 0x40) >> 1) | + (($in[11 * $chars + $idx] & 0x40) >> 2) | + (($in[12 * $chars + $idx] & 0x40) >> 3) | + (($in[13 * $chars + $idx] & 0x40) >> 4) | + (($in[14 * $chars + $idx] & 0x40) >> 5) | + (($in[15 * $chars + $idx] & 0x40) >> 6) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x20) << 2) | + (($in[1 * $chars + $idx] & 0x20) << 1) | + (($in[2 * $chars + $idx] & 0x20)) | + (($in[3 * $chars + $idx] & 0x20) >> 1) | + (($in[4 * $chars + $idx] & 0x20) >> 2) | + (($in[5 * $chars + $idx] & 0x20) >> 3) | + (($in[6 * $chars + $idx] & 0x20) >> 4) | + (($in[7 * $chars + $idx] & 0x20) >> 5) + ), + chr( + (($in[8 * $chars + $idx] & 0x20) << 2) | + (($in[9 * $chars + $idx] & 0x20) << 1) | + (($in[10 * $chars + $idx] & 0x20)) | + (($in[11 * $chars + $idx] & 0x20) >> 1) | + (($in[12 * $chars + $idx] & 0x20) >> 2) | + (($in[13 * $chars + $idx] & 0x20) >> 3) | + (($in[14 * $chars + $idx] & 0x20) >> 4) | + (($in[15 * $chars + $idx] & 0x20) >> 5) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x10) << 3) | + (($in[1 * $chars + $idx] & 0x10) << 2) | + (($in[2 * $chars + $idx] & 0x10) << 1) | + (($in[3 * $chars + $idx] & 0x10)) | + (($in[4 * $chars + $idx] & 0x10) >> 1) | + (($in[5 * $chars + $idx] & 0x10) >> 2) | + (($in[6 * $chars + $idx] & 0x10) >> 3) | + (($in[7 * $chars + $idx] & 0x10) >> 4) + ), + chr( + (($in[8 * $chars + $idx] & 0x10) << 3) | + (($in[9 * $chars + $idx] & 0x10) << 2) | + (($in[10 * $chars + $idx] & 0x10) << 1) | + (($in[11 * $chars + $idx] & 0x10)) | + (($in[12 * $chars + $idx] & 0x10) >> 1) | + (($in[13 * $chars + $idx] & 0x10) >> 2) | + (($in[14 * $chars + $idx] & 0x10) >> 3) | + (($in[15 * $chars + $idx] & 0x10) >> 4) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x08) << 4) | + (($in[1 * $chars + $idx] & 0x08) << 3) | + (($in[2 * $chars + $idx] & 0x08) << 2) | + (($in[3 * $chars + $idx] & 0x08) << 1) | + (($in[4 * $chars + $idx] & 0x08)) | + (($in[5 * $chars + $idx] & 0x08) >> 1) | + (($in[6 * $chars + $idx] & 0x08) >> 2) | + (($in[7 * $chars + $idx] & 0x08) >> 3) + ), + chr( + (($in[8 * $chars + $idx] & 0x08) << 4) | + (($in[9 * $chars + $idx] & 0x08) << 3) | + (($in[10 * $chars + $idx] & 0x08) << 2) | + (($in[11 * $chars + $idx] & 0x08) << 1) | + (($in[12 * $chars + $idx] & 0x08)) | + (($in[13 * $chars + $idx] & 0x08) >> 1) | + (($in[14 * $chars + $idx] & 0x08) >> 2) | + (($in[15 * $chars + $idx] & 0x08) >> 3) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x04) << 5) | + (($in[1 * $chars + $idx] & 0x04) << 4) | + (($in[2 * $chars + $idx] & 0x04) << 3) | + (($in[3 * $chars + $idx] & 0x04) << 2) | + (($in[4 * $chars + $idx] & 0x04) << 1) | + (($in[5 * $chars + $idx] & 0x04)) | + (($in[6 * $chars + $idx] & 0x04) >> 1) | + (($in[7 * $chars + $idx] & 0x04) >> 2) + ), + chr( + (($in[8 * $chars + $idx] & 0x04) << 5) | + (($in[9 * $chars + $idx] & 0x04) << 4) | + (($in[10 * $chars + $idx] & 0x04) << 3) | + (($in[11 * $chars + $idx] & 0x04) << 2) | + (($in[12 * $chars + $idx] & 0x04) << 1) | + (($in[13 * $chars + $idx] & 0x04)) | + (($in[14 * $chars + $idx] & 0x04) >> 1) | + (($in[15 * $chars + $idx] & 0x04) >> 2) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x02) << 6) | + (($in[1 * $chars + $idx] & 0x02) << 5) | + (($in[2 * $chars + $idx] & 0x02) << 4) | + (($in[3 * $chars + $idx] & 0x02) << 3) | + (($in[4 * $chars + $idx] & 0x02) << 2) | + (($in[5 * $chars + $idx] & 0x02) << 1) | + (($in[6 * $chars + $idx] & 0x02)) | + (($in[7 * $chars + $idx] & 0x02) >> 1) + ), + chr( + (($in[8 * $chars + $idx] & 0x02) << 6) | + (($in[9 * $chars + $idx] & 0x02) << 5) | + (($in[10 * $chars + $idx] & 0x02) << 4) | + (($in[11 * $chars + $idx] & 0x02) << 3) | + (($in[12 * $chars + $idx] & 0x02) << 2) | + (($in[13 * $chars + $idx] & 0x02) << 1) | + (($in[14 * $chars + $idx] & 0x02)) | + (($in[15 * $chars + $idx] & 0x02) >> 1) + ), + chr(0), + chr( + (($in[0 * $chars + $idx] & 0x01) << 7) | + (($in[1 * $chars + $idx] & 0x01) << 6) | + (($in[2 * $chars + $idx] & 0x01) << 5) | + (($in[3 * $chars + $idx] & 0x01) << 4) | + (($in[4 * $chars + $idx] & 0x01) << 3) | + (($in[5 * $chars + $idx] & 0x01) << 2) | + (($in[6 * $chars + $idx] & 0x01) << 1) | + (($in[7 * $chars + $idx] & 0x01)) + ), + chr( + (($in[8 * $chars + $idx] & 0x01) << 7) | + (($in[9 * $chars + $idx] & 0x01) << 6) | + (($in[10 * $chars + $idx] & 0x01) << 5) | + (($in[11 * $chars + $idx] & 0x01) << 4) | + (($in[12 * $chars + $idx] & 0x01) << 3) | + (($in[13 * $chars + $idx] & 0x01) << 2) | + (($in[14 * $chars + $idx] & 0x01) >> 1) | + (($in[15 * $chars + $idx] & 0x01)) + ), + chr(0) + ]); + } + + public function __construct(array $unifontFile) + { + $this -> unifontFile = $unifontFile; + } + + public function getGlyph($codePoint) + { + // Binary search for correct line. + $min = 0; + $max = count($this -> unifontFile) - 1; + $foundId = 0; + // Bias toward low side if file is > 255. + $m = min(count($this -> unifontFile) - 1, 255); + while ($min <= $max) { + $thisCodePoint = hexdec(substr($this -> unifontFile[$m], 0, 4)); + if ($codePoint === $thisCodePoint) { + $foundId = $m; + break; + } else if ($codePoint < $thisCodePoint) { + $max = $m - 1; + } else { + $min = $m + 1; + } + $m = floor(($min + $max) / 2); + } + $unifontLine = $this -> unifontFile[$foundId]; + + // Convert to column format + $binStr = unpack("C*", pack("H*", substr($unifontLine, 5))); + $bytes = count($binStr); + if ($bytes == 32) { + $width = 16; + $colFormat = UnifontGlyphFactory::colFormat16($binStr); + } else if ($bytes == 16) { + $width = 8; + $colFormat = UnifontGlyphFactory::colFormat8($binStr); + } + // Write to obj + $glyph = new ColumnFormatGlyph(); + $glyph -> width = $width; + $glyph -> data = $colFormat; + return $glyph; + } +} diff --git a/src/Mike42/Escpos/Experimental/Unifont/UnifontPrintBuffer.php b/src/Mike42/Escpos/Experimental/Unifont/UnifontPrintBuffer.php new file mode 100644 index 00000000..83b0a124 --- /dev/null +++ b/src/Mike42/Escpos/Experimental/Unifont/UnifontPrintBuffer.php @@ -0,0 +1,91 @@ + unifont = new UnifontGlyphFactory($unifontFileLines); + // Everything else is null + $this -> printer = null; + $this -> fontMap = null; + $this -> started = false; + } + + public function writeChar(int $codePoint) + { + if ($codePoint == 10) { + $this -> write("\n"); + } else if ($codePoint == 13) { + // Ignore CR char + } else { + // Straight column-format prints + $this -> fontMap -> writeChar($codePoint); + } + } + + public function writeText(string $text) + { + if (!$this -> started) { + $mode = Printer::MODE_FONT_B | Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH; + $this -> printer -> getPrintConnector() -> write(Printer::ESC . "!" . chr($mode)); + $this -> printer -> selectUserDefinedCharacterSet(true); + } + // Normalize text - this replaces combining characters with composed glyphs, and also helps us eliminated bad UTF-8 early + $text = \Normalizer::normalize($text); + if ($text === false) { + throw new \Exception("Input must be UTF-8"); + } + // Iterate code points + $codePointIterator = \IntlBreakIterator::createCodePointInstance(); + $codePointIterator->setText($text); + while ($codePointIterator->next() > 0) { + $codePoint = $codePointIterator->getLastCodePoint(); + $this->writeChar($codePoint); + } + } + + public function flush() + { + } + + public function setPrinter(Printer $printer = null) + { + $this -> printer = $printer; + $this -> fontMap = new FontMap($this -> unifont, $this -> printer); + } + + public function writeTextRaw(string $text) + { + } + + public function getPrinter() + { + return $this -> printer; + } + + /** + * Write data to the underlying connector. + * + * @param string $data + */ + private function write($data) + { + $this -> printer -> getPrintConnector() -> write($data); + } +} diff --git a/src/Mike42/Escpos/GdEscposImage.php b/src/Mike42/Escpos/GdEscposImage.php index 32edf76e..9f255c6f 100644 --- a/src/Mike42/Escpos/GdEscposImage.php +++ b/src/Mike42/Escpos/GdEscposImage.php @@ -3,7 +3,7 @@ * This file is part of escpos-php: PHP receipt printer library for use with * ESC/POS-compatible thermal and impact printers. * - * Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >, + * Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >, * incorporating modifications by others. See CONTRIBUTORS.md for a full list. * * This software is distributed under the terms of the MIT license. See LICENSE.md @@ -12,7 +12,6 @@ namespace Mike42\Escpos; -use Mike42\Escpos\EscposImage; use Exception; /** @@ -27,7 +26,7 @@ class GdEscposImage extends EscposImage * @throws Exception if the image format is not supported, * or the file cannot be opened. */ - protected function loadImageData($filename = null) + protected function loadImageData(string $filename = null) { if ($filename === null) { /* Set to blank image */ diff --git a/src/Mike42/Escpos/ImagickEscposImage.php b/src/Mike42/Escpos/ImagickEscposImage.php index 13851a4d..1b0aaa9d 100644 --- a/src/Mike42/Escpos/ImagickEscposImage.php +++ b/src/Mike42/Escpos/ImagickEscposImage.php @@ -14,7 +14,6 @@ use Exception; use Imagick; -use Mike42\Escpos\EscposImage; /** * Implementation of EscposImage using the Imagick PHP plugin. @@ -26,12 +25,12 @@ class ImagickEscposImage extends EscposImage * * @param Imagick $im Image to load from */ - public function readImageFromImagick(\Imagick $im) + public function readImageFromImagick(Imagick $im) { /* Strip transparency */ $im = self::alphaRemove($im); /* Threshold */ - $im -> setImageType(\Imagick::IMGTYPE_TRUECOLOR); // Remove transparency (good for PDF's) + $im -> setImageType(Imagick::IMGTYPE_TRUECOLOR); // Remove transparency (good for PDF's) $max = $im->getQuantumRange(); $max = $max["quantumRangeLong"]; $im -> thresholdImage(0.5 * $max); @@ -89,7 +88,7 @@ protected function getColumnFormatFromFile($filename = null, $highDensityVertica * @throws Exception if the image format is not supported, * or the file cannot be opened. */ - protected function loadImageData($filename = null) + protected function loadImageData(string $filename = null) { if ($filename === null) { /* Set to blank image */ @@ -109,7 +108,7 @@ protected function loadImageData($filename = null) * Height of printed line in dots. 8 or 24. * @return string[] */ - private function getColumnFormatFromImage(Imagick $im, $lineHeight) + private function getColumnFormatFromImage(Imagick $im, int $lineHeight) { $imgWidth = $im->getimagewidth(); if ($imgWidth == $lineHeight) { @@ -212,7 +211,7 @@ protected function getRasterFormatFromFile($filename = null) * or invalid page number is requested. * @return array Array of images, retrieved from the PDF file. */ - public static function loadPdf($pdfFile, $pageWidth = 550) + public static function loadPdf($pdfFile, int $pageWidth = 550) { if (!EscposImage::isImagickLoaded()) { throw new Exception(__FUNCTION__ . " requires imagick extension."); @@ -222,7 +221,7 @@ public static function loadPdf($pdfFile, $pageWidth = 550) * density to use to achieve $pageWidth */ try { - $image = new \Imagick(); + $image = new Imagick(); $testRes = 2; // Test resolution $image -> setresolution($testRes, $testRes); /* Load document just to measure geometry */ @@ -265,9 +264,9 @@ public static function loadPdf($pdfFile, $pageWidth = 550) */ private static function alphaRemove(Imagick $im) { - $flat = new \Imagick(); + $flat = new Imagick(); $flat -> newImage($im -> getimagewidth(), $im -> getimageheight(), "white", $im -> getimageformat()); - $flat -> compositeimage($im, \Imagick::COMPOSITE_OVER, 0, 0); + $flat -> compositeimage($im, Imagick::COMPOSITE_OVER, 0, 0); return $flat; } } diff --git a/src/Mike42/Escpos/NativeEscposImage.php b/src/Mike42/Escpos/NativeEscposImage.php index e85c942b..5a3b79cb 100644 --- a/src/Mike42/Escpos/NativeEscposImage.php +++ b/src/Mike42/Escpos/NativeEscposImage.php @@ -12,13 +12,26 @@ namespace Mike42\Escpos; -use Mike42\Escpos\EscposImage; +use Mike42\GfxPhp\Image; /** * Implementation of EscposImage using only native PHP. - * TODO: wbmp, pbm, bmp files. */ class NativeEscposImage extends EscposImage { - + protected function loadImageData(string $filename = null) + { + $image = Image::fromFile($filename) -> toRgb() -> toBlackAndWhite(); + $imgHeight = $image -> getHeight(); + $imgWidth = $image -> getWidth(); + $imgData = str_repeat("\0", $imgHeight * $imgWidth); + for ($y = 0; $y < $imgHeight; $y++) { + for ($x = 0; $x < $imgWidth; $x++) { + $imgData[$y * $imgWidth + $x] = $image -> getPixel($x, $y) == 0 ? 0: 1; + } + } + $this -> setImgWidth($imgWidth); + $this -> setImgHeight($imgHeight); + $this -> setImgData($imgData); + } } diff --git a/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php b/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php index 4e041765..d126b9d9 100644 --- a/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php +++ b/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php @@ -13,6 +13,7 @@ namespace Mike42\Escpos\PrintBuffers; use LogicException; +use Mike42\Escpos\CodePage; use Mike42\Escpos\Printer; /** @@ -27,11 +28,6 @@ class EscposPrintBuffer implements PrintBuffer */ const COMPRESS_CACHE = true; - /** - * The input encoding of the buffer. - */ - const INPUT_ENCODING = "UTF-8"; - /** * Un-recognised characters will be replaced with this. */ @@ -39,13 +35,13 @@ class EscposPrintBuffer implements PrintBuffer /** * @var array $available - * This array Maps ESC/POS character tables to names iconv encodings + * Map code points to printer-specific code page numbers which contain them */ private $available = null; /** * @var array $encode - * Maps of UTF-8 to code-pages + * Map code pages to a map of code points to encoding-specific characters 128-255 */ private $encode = null; @@ -84,42 +80,43 @@ public function setPrinter(Printer $printer = null) } } - public function writeText($text) + public function writeText(string $text) { - if ($this -> printer == null) { + if ($this->printer == null) { throw new LogicException("Not attached to a printer."); } - if ($text == null) { - return; - } - if (!mb_detect_encoding($text, self::INPUT_ENCODING, true)) { - // Assume that the user has already put non-UTF8 into the target encoding. - return $this -> writeTextRaw($text); + // Normalize text - this replaces combining characters with composed glyphs, and also helps us eliminated bad UTF-8 early + $text = \Normalizer::normalize($text); + if ($text === false) { + throw new \Exception("Input must be UTF-8"); } - $i = 0; - $j = 0; - $len = mb_strlen($text, self::INPUT_ENCODING); - while ($i < $len) { - $matching = true; - if (($encoding = $this -> identifyText(mb_substr($text, $i, 1, self::INPUT_ENCODING))) === false) { - // Un-encodeable text - $encoding = $this -> getPrinter() -> getCharacterTable(); + // Iterate code points + $codePointIterator = \IntlBreakIterator::createCodePointInstance(); + $codePointIterator->setText($text); + $encoding = $this->printer->getCharacterTable(); + $currentBlock = []; + while ($codePointIterator->next() > 0) { + // Write each code point + $codePoint = $codePointIterator->getLastCodePoint(); + // See if we need to change code pages + $matching = !isset($this->available[$codePoint]) || isset($this->encode[$encoding][$codePoint]); + if ($matching) { + $currentBlock[] = $codePoint; + } else { + // Write what we have + $this->writeTextUsingEncoding($currentBlock, $encoding); + // New encoding.. + $encoding = self::identifyText($codePoint); + $currentBlock = [$codePoint]; } - $i++; - $j = 1; - do { - $char = mb_substr($text, $i, 1, self::INPUT_ENCODING); - $matching = !isset($this -> available[$char]) || isset($this -> available[$char][$encoding]); - if ($matching) { - $i++; - $j++; - } - } while ($matching && $i < $len); - $this -> writeTextUsingEncoding(mb_substr($text, $i - $j, $j, self::INPUT_ENCODING), $encoding); + } + // Write out last bytes + if (count($currentBlock) != 0) { + $this->writeTextUsingEncoding($currentBlock, $encoding); } } - public function writeTextRaw($text) + public function writeTextRaw(string $text) { if ($this -> printer == null) { throw new LogicException("Not attached to a printer."); @@ -148,26 +145,19 @@ public function writeTextRaw($text) * Return an encoding which we can start to use for outputting this text. * Later parts of the text need not be included in the returned code page. * - * @param string $text Input text to check. + * @param int $codePoint Code point to check. * @return boolean|integer Code page number, or FALSE if the text is not * printable on any supported encoding. */ - private function identifyText($text) + private function identifyText(int $codePoint) { - // TODO Replace this with an algorithm to choose the encoding which will - // encode the farthest into the string, to minimise code page changes. - $char = mb_substr($text, 0, 1, self::INPUT_ENCODING); - if (!isset($this -> available[$char])) { + if (!isset($this -> available[$codePoint])) { /* Character not available anywhere */ return false; } - foreach ($this -> available[$char] as $encodingNo => $true) { - /* Return first code-page where it is available */ - return $encodingNo; - } - return false; + return $this -> available[$codePoint]; } - + /** * Based on the printer's connector, compute (or load a cached copy of) maps * of UTF character to unicode characters for later use. @@ -198,32 +188,39 @@ private function loadAvailableCharacters() } /* Generate conversion tables */ + $encodeLegacy = []; $encode = []; $available = []; foreach ($supportedCodePages as $num => $codePage) { - $encode[$num] = []; + $encodeLegacy[$num] = []; if (!$codePage -> isEncodable()) { continue; } - $map = $codePage -> getData(); + $map = $codePage -> getDataArray(); + $encodeMap = []; for ($char = 128; $char <= 255; $char++) { - $utf8 = mb_substr($map, $char - 128, 1, self::INPUT_ENCODING); - if ($utf8 == " ") { // Skip placeholders + $codePoint = $map[$char - 128]; + if ($codePoint == CodePage::MISSING_CHAR_CODE) { // Skip placeholders continue; } - if (!isset($available[$utf8])) { - $available[$utf8] = []; + $encodeMap[$codePoint] = $char; + if (!isset($available[$codePoint])) { + $available[$codePoint] = $num; } - $available[$utf8][$num] = true; - $encode[$num][$utf8] = chr($char); } + $encode[$num] = $encodeMap; } /* Use generated data */ - $dataArray = ["available" => $available, "encode" => $encode, "key" => $cacheKey]; - $this -> available = $dataArray["available"]; - $this -> encode = $dataArray["encode"]; + $dataArray = [ + "available" => $available, + "encode" => $encode, + "key" => $cacheKey + ]; + $this -> available = $available; + $this -> encode = $encode; + $cacheData = serialize($dataArray); if (self::COMPRESS_CACHE) { $cacheData = gzcompress($cacheData); @@ -235,31 +232,35 @@ private function loadAvailableCharacters() /** * Encode a block of text using the specified map, and write it to the printer. * - * @param string $text Text to print, UTF-8 format. + * @param array $codePoints Text to print, as list of unicode code points * @param integer $encodingNo Encoding number to use- assumed to exist. */ - private function writeTextUsingEncoding($text, $encodingNo) + private function writeTextUsingEncoding(array $codePoints, int $encodingNo) { $encodeMap = $this -> encode[$encodingNo]; - $len = mb_strlen($text, self::INPUT_ENCODING); + $len = count($codePoints); + $rawText = str_repeat(self::REPLACEMENT_CHAR, $len); - $j = 0; + $bytesWritten = 0; + $cr = 0x0D; // extra character from line endings on Windows for ($i = 0; $i < $len; $i++) { - $char = mb_substr($text, $i, 1, self::INPUT_ENCODING); - if (isset($encodeMap[$char])) { - $rawText[$j] = $encodeMap[$char]; - } elseif (self::asciiCheck($char)) { - $rawText[$j] = $char; - } elseif ($char === "\r") { - /* Skip past Windows line endings (UTF-8 usage) */ + $codePoint = $codePoints[$i]; + if (isset($encodeMap[$codePoint])) { + // Printable via selected code page + $rawText[$bytesWritten] = chr($encodeMap[$codePoint]); + } elseif (($codePoint > 31 && $codePoint < 127) || $codePoint == 10) { + // Printable as ASCII + $rawText[$bytesWritten] = chr($codePoint); + } elseif ($codePoint === $cr) { + // Skip past Windows line endings, LF is fine continue; } - $j++; + $bytesWritten++; } if ($this -> printer -> getCharacterTable() != $encodingNo) { $this -> printer -> selectCharacterTable($encodingNo); } - $this -> writeTextRaw(substr($rawText, 0, $j)); + $this -> writeTextRaw(substr($rawText, 0, $bytesWritten)); } /** @@ -267,7 +268,7 @@ private function writeTextUsingEncoding($text, $encodingNo) * * @param string $data */ - private function write($data) + private function write(string $data) { $this -> printer -> getPrintConnector() -> write($data); } @@ -279,7 +280,7 @@ private function write($data) * @param boolean $extended True to allow 128-256 values also (excluded by default) * @return boolean True if the character is printable, false if it is not. */ - private static function asciiCheck($char, $extended = false) + private static function asciiCheck(string $char, bool $extended = false) { if (strlen($char) != 1) { // Multi-byte string diff --git a/src/Mike42/Escpos/PrintBuffers/ImagePrintBuffer.php b/src/Mike42/Escpos/PrintBuffers/ImagePrintBuffer.php index d4fdefaf..b033383d 100644 --- a/src/Mike42/Escpos/PrintBuffers/ImagePrintBuffer.php +++ b/src/Mike42/Escpos/PrintBuffers/ImagePrintBuffer.php @@ -60,7 +60,7 @@ public function setPrinter(Printer $printer = null) $this -> printer = $printer; } - public function writeText($text) + public function writeText(string $text) { if ($this -> printer == null) { throw new LogicException("Not attached to a printer."); @@ -102,7 +102,7 @@ public function writeText($text) $this -> printer -> bitImage($escposImage, $size); } - public function writeTextRaw($text) + public function writeTextRaw(string $text) { if ($this -> printer == null) { throw new LogicException("Not attached to a printer."); @@ -120,7 +120,7 @@ public function writeTextRaw($text) * @param string $font * Font name or a filename */ - public function setFont($font) + public function setFont(string $font) { $this->font = $font; } @@ -128,7 +128,7 @@ public function setFont($font) /** * Numeric font size for rendering text to image */ - public function setFontSize($fontSize) + public function setFontSize(int $fontSize) { $this->fontSize = $fontSize; } diff --git a/src/Mike42/Escpos/PrintBuffers/PrintBuffer.php b/src/Mike42/Escpos/PrintBuffers/PrintBuffer.php index fcad6e9e..8e5321ff 100644 --- a/src/Mike42/Escpos/PrintBuffers/PrintBuffer.php +++ b/src/Mike42/Escpos/PrintBuffers/PrintBuffer.php @@ -52,12 +52,12 @@ public function setPrinter(Printer $printer = null); * * @param string $text Text to print */ - public function writeText($text); + public function writeText(string $text); /** * Accept 8-bit text in the current encoding and add it to the buffer. * * @param string $text Text to print, already the target encoding. */ - public function writeTextRaw($text); + public function writeTextRaw(string $text); } diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z index c0b9adb9..51214591 100644 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z and b/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-P822D.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-P822D.ser.z deleted file mode 100644 index 800630b6..00000000 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-P822D.ser.z and /dev/null differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-POS-5890.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-POS-5890.ser.z deleted file mode 100644 index 948e135c..00000000 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-POS-5890.ser.z and /dev/null differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-SP2000.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-SP2000.ser.z deleted file mode 100644 index c5ac146d..00000000 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-SP2000.ser.z and /dev/null differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-TEP-200M.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-TEP-200M.ser.z deleted file mode 100644 index 3e6b1902..00000000 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-TEP-200M.ser.z and /dev/null differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z index 3e6b1902..37a05d14 100644 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z and b/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z differ diff --git a/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z b/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z index ca1c7bca..b8c674d7 100644 Binary files a/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z and b/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z differ diff --git a/src/Mike42/Escpos/PrintConnectors/ApiPrintConnector.php b/src/Mike42/Escpos/PrintConnectors/ApiPrintConnector.php deleted file mode 100644 index 893a4858..00000000 --- a/src/Mike42/Escpos/PrintConnectors/ApiPrintConnector.php +++ /dev/null @@ -1,102 +0,0 @@ -httpClient = new Client(['base_uri' => $host]); - $this->printerId = $printerId; - $this->apiToken = $apiToken; - - $this->stream = ''; - } - - /** - * Print connectors should cause a NOTICE if they are deconstructed - * when they have not been finalized. - */ - public function __destruct() - { - if (! empty($this->stream)) { - trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE); - } - } - - /** - * Finish using this print connector (close file, socket, send - * accumulated output, etc). - */ - public function finalize() - { - /** @var Request $request */ - $request = $this->httpClient->post( - 'printers/'.$this->printerId.'/print?api_token='.$this->apiToken, - null, - $this->stream - ); - - /** @var Response $response */ - $response = $request->send(); - - if (! $response->isSuccessful()) { - throw new Exception( - sprintf('Failed to print. API returned "%s: %s"', $response->getStatusCode(), $response->getReasonPhrase()) - ); - } - - $this->stream = ''; - } - - /** - * Read data from the printer. - * - * @param string $len Length of data to read. - * @return string Data read from the printer. - */ - public function read($len) - { - return $this->stream; - } - - /** - * Write data to the print connector. - * - * @param string $data The data to write - */ - public function write($data) - { - $this->stream .= $data; - } -} diff --git a/src/Mike42/Escpos/PrintConnectors/CupsPrintConnector.php b/src/Mike42/Escpos/PrintConnectors/CupsPrintConnector.php index 497887f3..f92746ac 100644 --- a/src/Mike42/Escpos/PrintConnectors/CupsPrintConnector.php +++ b/src/Mike42/Escpos/PrintConnectors/CupsPrintConnector.php @@ -78,6 +78,9 @@ public function finalize() // Build command to work on data $tmpfname = tempnam(sys_get_temp_dir(), 'print-'); + if ($tmpfname === false) { + throw new Exception("Failed to create temp file for printing."); + } file_put_contents($tmpfname, $data); $cmd = sprintf( "lp -d %s %s", @@ -134,7 +137,7 @@ protected function getCmdOutput($cmd) * Read data from the printer. * * @param string $len Length of data to read. - * @return Data read from the printer, or false where reading is not possible. + * @return string Data read from the printer, or false where reading is not possible. */ public function read($len) { diff --git a/src/Mike42/Escpos/PrintConnectors/MultiplePrintConnector.php b/src/Mike42/Escpos/PrintConnectors/MultiplePrintConnector.php new file mode 100644 index 00000000..a6da2671 --- /dev/null +++ b/src/Mike42/Escpos/PrintConnectors/MultiplePrintConnector.php @@ -0,0 +1,40 @@ + connectors = $connectors; + } + + public function finalize() + { + foreach ($this -> connectors as $connector) { + $connector -> finalize(); + } + } + + public function read($len) + { + // Cannot write + return false; + } + + public function write($data) + { + foreach ($this -> connectors as $connector) { + $connector -> write($data); + } + } + + public function __destruct() + { + // Do nothing + } +} diff --git a/src/Mike42/Escpos/PrintConnectors/PrintConnector.php b/src/Mike42/Escpos/PrintConnectors/PrintConnector.php index 4198dbc1..52527242 100644 --- a/src/Mike42/Escpos/PrintConnectors/PrintConnector.php +++ b/src/Mike42/Escpos/PrintConnectors/PrintConnector.php @@ -34,7 +34,7 @@ public function finalize(); * Read data from the printer. * * @param string $len Length of data to read. - * @return Data read from the printer, or false where reading is not possible. + * @return string Data read from the printer, or false where reading is not possible. */ public function read($len); diff --git a/src/Mike42/Escpos/PrintConnectors/UriPrintConnector.php b/src/Mike42/Escpos/PrintConnectors/UriPrintConnector.php index c51d2bf3..82a57e90 100644 --- a/src/Mike42/Escpos/PrintConnectors/UriPrintConnector.php +++ b/src/Mike42/Escpos/PrintConnectors/UriPrintConnector.php @@ -1,6 +1,4 @@ runCopy($filename, $device)) { throw new Exception("Failed to copy file to printer"); diff --git a/src/Mike42/Escpos/Printer.php b/src/Mike42/Escpos/Printer.php index 753d2ea8..0b31bd39 100644 --- a/src/Mike42/Escpos/Printer.php +++ b/src/Mike42/Escpos/Printer.php @@ -17,7 +17,6 @@ use Mike42\Escpos\PrintBuffers\PrintBuffer; use Mike42\Escpos\PrintBuffers\EscposPrintBuffer; use Mike42\Escpos\PrintConnectors\PrintConnector; -use Mike42\Escpos\CapabilityProfile; /** * Main class for ESC/POS code generation @@ -388,7 +387,7 @@ public function __construct(PrintConnector $connector, CapabilityProfile $profil * available barcode types vary between printers. * @throws InvalidArgumentException Where the length or characters used in $content is invalid for the requested barcode format. */ - public function barcode($content, $type = Printer::BARCODE_CODE39) + public function barcode(string $content, int $type = Printer::BARCODE_CODE39) { /* Validate input */ self::validateInteger($type, 65, 73, __FUNCTION__, "Barcode type"); @@ -454,7 +453,7 @@ public function barcode($content, $type = Printer::BARCODE_CODE39) * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and * `Printer::IMG_DOUBLE_WIDTH` flags. */ - public function bitImage(EscposImage $img, $size = Printer::IMG_DEFAULT) + public function bitImage(EscposImage $img, int $size = Printer::IMG_DEFAULT) { self::validateInteger($size, 0, 3, __FUNCTION__); $rasterData = $img -> toRasterFormat(); @@ -474,7 +473,7 @@ public function bitImage(EscposImage $img, $size = Printer::IMG_DEFAULT) * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and * `Printer::IMG_DOUBLE_WIDTH` flags. */ - public function bitImageColumnFormat(EscposImage $img, $size = Printer::IMG_DEFAULT) + public function bitImageColumnFormat(EscposImage $img, int $size = Printer::IMG_DEFAULT) { $highDensityVertical = ! (($size & self::IMG_DOUBLE_HEIGHT) == Printer::IMG_DOUBLE_HEIGHT); $highDensityHorizontal = ! (($size & self::IMG_DOUBLE_WIDTH) == Printer::IMG_DOUBLE_WIDTH); @@ -509,7 +508,7 @@ public function close() * @param int $mode Cut mode, either Printer::CUT_FULL or Printer::CUT_PARTIAL. If not specified, `Printer::CUT_FULL` will be used. * @param int $lines Number of lines to feed */ - public function cut($mode = Printer::CUT_FULL, $lines = 3) + public function cut(int $mode = Printer::CUT_FULL, int $lines = 3) { // TODO validation on cut() inputs $this -> connector -> write(self::GS . "V" . chr($mode) . chr($lines)); @@ -520,7 +519,7 @@ public function cut($mode = Printer::CUT_FULL, $lines = 3) * * @param int $lines Number of lines to feed */ - public function feed($lines = 1) + public function feed(int $lines = 1) { self::validateInteger($lines, 1, 255, __FUNCTION__); if ($lines <= 1) { @@ -552,14 +551,14 @@ public function release() * * @param int $lines number of lines to feed. If not specified, 1 line will be fed. */ - public function feedReverse($lines = 1) + public function feedReverse(int $lines = 1) { self::validateInteger($lines, 1, 255, __FUNCTION__); $this -> connector -> write(self::ESC . "e" . chr($lines)); } /** - * @return number + * @return int */ public function getCharacterTable() { @@ -609,7 +608,7 @@ public function getPrinterCapabilityProfile() * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and * `Printer::IMG_DOUBLE_WIDTH` flags. */ - public function graphics(EscposImage $img, $size = Printer::IMG_DEFAULT) + public function graphics(EscposImage $img, int $size = Printer::IMG_DEFAULT) { self::validateInteger($size, 0, 3, __FUNCTION__); $rasterData = $img -> toRasterFormat(); @@ -648,9 +647,8 @@ public function initialize() * start/end bars, or truncated code Printer::PDF417_TRUNCATED with start bars only. * @throws Exception If this profile indicates that PDF417 code is not supported */ - public function pdf417Code($content, $width = 3, $heightMultiplier = 3, $dataColumnCount = 0, $ec = 0.10, $options = Printer::PDF417_STANDARD) + public function pdf417Code(string $content, int $width = 3, int $heightMultiplier = 3, int $dataColumnCount = 0, float $ec = 0.10, int $options = Printer::PDF417_STANDARD) { - self::validateString($content, __FUNCTION__, 'content'); self::validateInteger($width, 2, 8, __FUNCTION__, 'width'); self::validateInteger($heightMultiplier, 2, 8, __FUNCTION__, 'heightMultiplier'); self::validateInteger($dataColumnCount, 0, 30, __FUNCTION__, 'dataColumnCount'); @@ -687,7 +685,7 @@ public function pdf417Code($content, $width = 3, $heightMultiplier = 3, $dataCol * @param int $on_ms pulse ON time, in milliseconds. * @param int $off_ms pulse OFF time, in milliseconds. */ - public function pulse($pin = 0, $on_ms = 120, $off_ms = 240) + public function pulse(int $pin = 0, int $on_ms = 120, int $off_ms = 240) { self::validateInteger($pin, 0, 1, __FUNCTION__); self::validateInteger($on_ms, 1, 511, __FUNCTION__); @@ -703,9 +701,8 @@ public function pulse($pin = 0, $on_ms = 120, $off_ms = 240) * @param int $size Pixel size to use. Must be 1-16 (default 3) * @param int $model QR code model to use. Must be one of Printer::QR_MODEL_1, Printer::QR_MODEL_2 (default) or Printer::QR_MICRO (not supported by all printers). */ - public function qrCode($content, $ec = Printer::QR_ECLEVEL_L, $size = 3, $model = Printer::QR_MODEL_2) + public function qrCode(string $content, int $ec = Printer::QR_ECLEVEL_L, int$size = 3, int $model = Printer::QR_MODEL_2) { - self::validateString($content, __FUNCTION__); self::validateInteger($ec, 0, 3, __FUNCTION__); self::validateInteger($size, 1, 16, __FUNCTION__); self::validateInteger($model, 1, 3, __FUNCTION__); @@ -734,7 +731,7 @@ public function qrCode($content, $ec = Printer::QR_ECLEVEL_L, $size = 3, $model * * @param int $table The table to select. Available code tables are model-specific. */ - public function selectCharacterTable($table = 0) + public function selectCharacterTable(int $table = 0) { self::validateInteger($table, 0, 255, __FUNCTION__); $supported = $this -> profile -> getCodePages(); @@ -763,7 +760,7 @@ public function selectCharacterTable($table = 0) * * @param int $mode The mode to use. Default is Printer::MODE_FONT_A, with no special formatting. This has a similar effect to running initialize(). */ - public function selectPrintMode($mode = Printer::MODE_FONT_A) + public function selectPrintMode(int $mode = Printer::MODE_FONT_A) { $allModes = Printer::MODE_FONT_B | self::MODE_EMPHASIZED | self::MODE_DOUBLE_HEIGHT | self::MODE_DOUBLE_WIDTH | self::MODE_UNDERLINE; if (!is_integer($mode) || $mode < 0 || ($mode & $allModes) != $mode) { @@ -772,13 +769,23 @@ public function selectPrintMode($mode = Printer::MODE_FONT_A) $this -> connector -> write(self::ESC . "!" . chr($mode)); } - + + /** + * Select user-defined character set. + * + * @param bool $on True to enable user-defined character set, false to use built-in characters sets. + */ + public function selectUserDefinedCharacterSet($on = true) + { + $this -> connector -> write(self::ESC . "%". ($on ? chr(1) : chr(0))); + } + /** * Set barcode height. * * @param int $height Height in dots. If not specified, 8 will be used. */ - public function setBarcodeHeight($height = 8) + public function setBarcodeHeight(int $height = 8) { self::validateInteger($height, 1, 255, __FUNCTION__); $this -> connector -> write(self::GS . "h" . chr($height)); @@ -790,7 +797,7 @@ public function setBarcodeHeight($height = 8) * @param int $width Bar width in dots. If not specified, 3 will be used. * Values above 6 appear to have no effect. */ - public function setBarcodeWidth($width = 3) + public function setBarcodeWidth(int $width = 3) { self::validateInteger($width, 1, 255, __FUNCTION__); $this -> connector -> write(self::GS . "w" . chr($width)); @@ -803,7 +810,7 @@ public function setBarcodeWidth($width = 3) * or any combination of Printer::BARCODE_TEXT_ABOVE and Printer::BARCODE_TEXT_BELOW * flags to display the text. */ - public function setBarcodeTextPosition($position = Printer::BARCODE_TEXT_NONE) + public function setBarcodeTextPosition(int $position = Printer::BARCODE_TEXT_NONE) { self::validateInteger($position, 0, 3, __FUNCTION__, "Barcode text position"); $this -> connector -> write(self::GS . "H" . chr($position)); @@ -814,7 +821,7 @@ public function setBarcodeTextPosition($position = Printer::BARCODE_TEXT_NONE) * * @param boolean $on true for double strike, false for no double strike */ - public function setDoubleStrike($on = true) + public function setDoubleStrike(bool $on = true) { self::validateBoolean($on, __FUNCTION__); $this -> connector -> write(self::ESC . "G". ($on ? chr(1) : chr(0))); @@ -825,7 +832,7 @@ public function setDoubleStrike($on = true) * * @param int $color Color to use. Must be either Printer::COLOR_1 (default), or Printer::COLOR_2. */ - public function setColor($color = Printer::COLOR_1) + public function setColor(int $color = Printer::COLOR_1) { self::validateInteger($color, 0, 1, __FUNCTION__, "Color"); $this -> connector -> write(self::ESC . "r" . chr($color)); @@ -836,7 +843,7 @@ public function setColor($color = Printer::COLOR_1) * * @param boolean $on true for emphasis, false for no emphasis */ - public function setEmphasis($on = true) + public function setEmphasis(bool $on = true) { self::validateBoolean($on, __FUNCTION__); $this -> connector -> write(self::ESC . "E". ($on ? chr(1) : chr(0))); @@ -847,7 +854,7 @@ public function setEmphasis($on = true) * * @param int $font The font to use. Must be either Printer::FONT_A, Printer::FONT_B, or Printer::FONT_C. */ - public function setFont($font = Printer::FONT_A) + public function setFont(int $font = Printer::FONT_A) { self::validateInteger($font, 0, 2, __FUNCTION__); $this -> connector -> write(self::ESC . "M" . chr($font)); @@ -858,7 +865,7 @@ public function setFont($font = Printer::FONT_A) * * @param int $justification One of Printer::JUSTIFY_LEFT, Printer::JUSTIFY_CENTER, or Printer::JUSTIFY_RIGHT. */ - public function setJustification($justification = Printer::JUSTIFY_LEFT) + public function setJustification(int $justification = Printer::JUSTIFY_LEFT) { self::validateInteger($justification, 0, 2, __FUNCTION__); $this -> connector -> write(self::ESC . "a" . chr($justification)); @@ -872,7 +879,7 @@ public function setJustification($justification = Printer::JUSTIFY_LEFT) * @param int|null $height The height of each line, in dots. If not set, the printer * will reset to its default line spacing. */ - public function setLineSpacing($height = null) + public function setLineSpacing(int $height = null) { if ($height === null) { // Reset to default @@ -888,7 +895,7 @@ public function setLineSpacing($height = null) * * @param int $margin The left margin to set on to the print area, in dots. */ - public function setPrintLeftMargin($margin = 0) + public function setPrintLeftMargin(int $margin = 0) { self::validateInteger($margin, 0, 65535, __FUNCTION__); $this -> connector -> write(Printer::GS . 'L' . self::intLowHigh($margin, 2)); @@ -900,7 +907,7 @@ public function setPrintLeftMargin($margin = 0) * * @param int $width The width of the page print area, in dots. */ - public function setPrintWidth($width = 512) + public function setPrintWidth(int $width = 512) { self::validateInteger($width, 1, 65535, __FUNCTION__); $this -> connector -> write(Printer::GS . 'W' . self::intLowHigh($width, 2)); @@ -932,7 +939,7 @@ public function setPrintBuffer(PrintBuffer $buffer) * * @param boolean $on True to enable, false to disable. */ - public function setReverseColors($on = true) + public function setReverseColors(bool $on = true) { self::validateBoolean($on, __FUNCTION__); $this -> connector -> write(self::GS . "B" . ($on ? chr(1) : chr(0))); @@ -944,30 +951,21 @@ public function setReverseColors($on = true) * @param int $widthMultiplier Multiple of the regular height to use (range 1 - 8) * @param int $heightMultiplier Multiple of the regular height to use (range 1 - 8) */ - public function setTextSize($widthMultiplier, $heightMultiplier) + public function setTextSize(int $widthMultiplier, int $heightMultiplier) { self::validateInteger($widthMultiplier, 1, 8, __FUNCTION__); self::validateInteger($heightMultiplier, 1, 8, __FUNCTION__); - $c = pow(2, 4) * ($widthMultiplier - 1) + ($heightMultiplier - 1); + $c = (2 << 3) * ($widthMultiplier - 1) + ($heightMultiplier - 1); $this -> connector -> write(self::GS . "!" . chr($c)); } /** * Set underline for printed text. * - * Argument can be true/false, or one of UNDERLINE_NONE, - * UNDERLINE_SINGLE or UNDERLINE_DOUBLE. - * * @param int $underline Either true/false, or one of Printer::UNDERLINE_NONE, Printer::UNDERLINE_SINGLE or Printer::UNDERLINE_DOUBLE. Defaults to Printer::UNDERLINE_SINGLE. */ - public function setUnderline($underline = Printer::UNDERLINE_SINGLE) + public function setUnderline(int $underline = Printer::UNDERLINE_SINGLE) { - /* Map true/false to underline constants */ - if ($underline === true) { - $underline = Printer::UNDERLINE_SINGLE; - } elseif ($underline === false) { - $underline = Printer::UNDERLINE_NONE; - } /* Set the underline */ self::validateInteger($underline, 0, 2, __FUNCTION__); $this -> connector -> write(self::ESC . "-" . chr($underline)); @@ -978,9 +976,8 @@ public function setUnderline($underline = Printer::UNDERLINE_SINGLE) * * @param boolean $on True to enable, false to disable. */ - public function setUpsideDown($on = true) + public function setUpsideDown(bool $on = true) { - self::validateBoolean($on, __FUNCTION__); $this -> connector -> write(self::ESC . "{" . ($on ? chr(1) : chr(0))); } @@ -990,26 +987,25 @@ public function setUpsideDown($on = true) * Text should either be followed by a line-break, or feed() should be called * after this to clear the print buffer. * - * @param string $str Text to print + * @param string $str Text to print, as UTF-8 */ - public function text($str = "") + public function text(string $str) { - self::validateString($str, __FUNCTION__); $this -> buffer -> writeText((string)$str); } /** - * Add Chinese text to the buffer. This is a specific workaround for the common Zijang printer- The printer will be switched to a two-byte mode and sent GBK-encoded text. + * Add Chinese text to the buffer. This is a specific workaround for Zijang printers- + * The printer will be switched to a two-byte mode and sent GBK-encoded text. * * Support for this will be merged into a print buffer. * * @param string $str Text to print, as UTF-8 */ - public function textChinese($str = "") + public function textChinese(string $str = "") { - self::validateString($str, __FUNCTION__); $this -> connector -> write(self::FS . "&"); - $str = iconv("UTF-8", "GBK//IGNORE", $str); + $str = \UConverter::transcode($str, "GBK", "UTF-8"); $this -> buffer -> writeTextRaw((string)$str); $this -> connector -> write(self::FS . "."); } @@ -1022,9 +1018,8 @@ public function textChinese($str = "") * * @param string $str Text to print */ - public function textRaw($str = "") + public function textRaw(string $str = "") { - self::validateString($str, __FUNCTION__); $this -> buffer -> writeTextRaw((string)$str); } @@ -1037,7 +1032,7 @@ public function textRaw($str = "") * @param string $m Modifier/variant for function. Often '0' where used. * @throws InvalidArgumentException Where the input lengths are bad. */ - protected function wrapperSend2dCodeData($fn, $cn, $data = '', $m = '') + protected function wrapperSend2dCodeData(string $fn, string $cn, string$data = '', string $m = '') { if (strlen($m) > 1 || strlen($cn) != 1 || strlen($fn) != 1) { throw new InvalidArgumentException("wrapperSend2dCodeData: cn and fn must be one character each."); @@ -1054,7 +1049,7 @@ protected function wrapperSend2dCodeData($fn, $cn, $data = '', $m = '') * @param string $data Data to send. * @throws InvalidArgumentException Where the input lengths are bad. */ - protected function wrapperSendGraphicsData($m, $fn, $data = '') + protected function wrapperSendGraphicsData(string $m, string $fn, string$data = '') { if (strlen($m) != 1 || strlen($fn) != 1) { throw new InvalidArgumentException("wrapperSendGraphicsData: m and fn must be one character each."); @@ -1070,7 +1065,7 @@ protected function wrapperSendGraphicsData($m, $fn, $data = '') * @param boolean $long True to use 4 bytes, false to use 2 * @return string */ - protected static function dataHeader(array $inputs, $long = true) + protected static function dataHeader(array $inputs, bool $long = true) { $outp = []; foreach ($inputs as $input) { @@ -1090,7 +1085,7 @@ protected static function dataHeader(array $inputs, $long = true) * @param int $input Input number * @param int $length The number of bytes to output (1 - 4). */ - protected static function intLowHigh($input, $length) + protected static function intLowHigh(int $input, int $length) { $maxInput = (256 << ($length * 8) - 1); self::validateInteger($length, 1, 4, __FUNCTION__); @@ -1109,7 +1104,7 @@ protected static function intLowHigh($input, $length) * @param boolean $test the input to test * @param string $source the name of the function calling this */ - protected static function validateBoolean($test, $source) + protected static function validateBoolean(bool $test, string $source) { if (!($test === true || $test === false)) { throw new InvalidArgumentException("Argument to $source must be a boolean"); @@ -1125,7 +1120,7 @@ protected static function validateBoolean($test, $source) * @param string $source the name of the function calling this * @param string $argument the name of the invalid parameter */ - protected static function validateFloat($test, $min, $max, $source, $argument = "Argument") + protected static function validateFloat(float $test, float $min, float $max, string $source, string $argument = "Argument") { if (!is_numeric($test)) { throw new InvalidArgumentException("$argument given to $source must be a float, but '$test' was given."); @@ -1144,7 +1139,7 @@ protected static function validateFloat($test, $min, $max, $source, $argument = * @param string $source the name of the function calling this * @param string $argument the name of the invalid parameter */ - protected static function validateInteger($test, $min, $max, $source, $argument = "Argument") + protected static function validateInteger(int $test, int $min, int $max, string $source, string $argument = "Argument") { self::validateIntegerMulti($test, [[$min, $max]], $source, $argument); } @@ -1158,7 +1153,7 @@ protected static function validateInteger($test, $min, $max, $source, $argument * @param string $source the name of the function calling this * @param string $argument the name of the invalid parameter */ - protected static function validateIntegerMulti($test, array $ranges, $source, $argument = "Argument") + protected static function validateIntegerMulti(int $test, array $ranges, string $source, string $argument = "Argument") { if (!is_integer($test)) { throw new InvalidArgumentException("$argument given to $source must be a number, but '$test' was given."); @@ -1184,21 +1179,6 @@ protected static function validateIntegerMulti($test, array $ranges, $source, $a } } - /** - * Throw an exception if the argument given can't be cast to a string - * - * @param string $test the input to test - * @param string $source the name of the function calling this - * @param string $argument the name of the parameter being validated - * @throws InvalidArgumentException Where the argument is not valid - */ - protected static function validateString($test, $source, $argument = "Argument") - { - if (is_object($test) && !method_exists($test, '__toString')) { - throw new InvalidArgumentException("$argument to $source must be a string"); - } - } - /** * Throw an exception if the argument doesn't match the given regex. * @@ -1208,7 +1188,7 @@ protected static function validateString($test, $source, $argument = "Argument") * @param string $argument the name of the parameter being validated * @throws InvalidArgumentException Where the argument is not valid */ - protected static function validateStringRegex($test, $source, $regex, $argument = "Argument") + protected static function validateStringRegex(string $test, string $source, string $regex, string $argument = "Argument") { if (preg_match($regex, $test) === 0) { throw new InvalidArgumentException("$argument given to $source is invalid. It should match regex '$regex', but '$test' was given."); diff --git a/src/Mike42/Escpos/resources/capabilities.json b/src/Mike42/Escpos/resources/capabilities.json index c60cac0d..92420f1c 100644 --- a/src/Mike42/Escpos/resources/capabilities.json +++ b/src/Mike42/Escpos/resources/capabilities.json @@ -173,6 +173,11 @@ "name": "CP855", "python_encode": "cp855" }, + "CP856": { + "iconv": "CP856", + "name": "CP856", + "python_encode": "cp856" + }, "CP857": { "iconv": "CP857", "name": "CP857", @@ -235,6 +240,11 @@ "name": "CP932", "python_encode": "cp932" }, + "ISO_8859-1": { + "iconv": "ISO_8859-1", + "name": "ISO_8859-1", + "python_encode": "latin_1" + }, "ISO_8859-15": { "iconv": "ISO_8859-15", "name": "ISO_8859-15", @@ -245,11 +255,41 @@ "name": "ISO_8859-2", "python_encode": "iso8859_2" }, + "ISO_8859-3": { + "iconv": "ISO_8859-3", + "name": "ISO_8859-3", + "python_encode": "iso8859_3" + }, + "ISO_8859-4": { + "iconv": "ISO_8859-4", + "name": "ISO_8859-4", + "python_encode": "iso8859_4" + }, + "ISO_8859-5": { + "iconv": "ISO_8859-5", + "name": "ISO_8859-5", + "python_encode": "iso8859_5" + }, + "ISO_8859-6": { + "iconv": "ISO_8859-6", + "name": "ISO_8859-6", + "python_encode": "iso8859_6" + }, "ISO_8859-7": { "iconv": "ISO_8859-7", "name": "ISO_8859-7", "python_encode": "iso8859_7" }, + "ISO_8859-8": { + "iconv": "ISO_8859-8", + "name": "ISO_8859-8", + "python_encode": "iso8859_8" + }, + "ISO_8859-9": { + "iconv": "ISO_8859-9", + "name": "ISO_8859-9", + "python_encode": "iso8859_9" + }, "OXHOO-EUROPEAN": { "data": [ "\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5", @@ -337,6 +377,74 @@ "notes": "This is a two-line, ESC/POS-aware customer display from Oxhoo. The ESC/POS command mode can be activated persistently by sending:\n\n echo -ne \"\\n\\x02\\x05\\x43\\x31\\x03\" > /dev/ttyUSB0\n", "vendor": "Oxhoo" }, + "CT-S651": { + "codePages": { + "0": "CP437", + "1": "CP932", + "2": "CP850", + "3": "CP860", + "4": "CP863", + "5": "CP865", + "6": "CP852", + "7": "CP866", + "8": "CP857", + "9": "CP1252", + "16": "CP1252", + "17": "CP866", + "18": "CP852", + "19": "CP858", + "20": "Unknown", + "21": "Unknown", + "25": "Unknown", + "26": "Unknown", + "30": "TCVN-3-1", + "31": "TCVN-3-2", + "40": "CP864", + "255": "Unknown" + }, + "colors": { + "0": "black", + "1": "red" + }, + "features": { + "barcodeA": true, + "barcodeB": true, + "bitImageColumn": true, + "bitImageRaster": true, + "graphics": true, + "highDensity": true, + "paperFullCut": true, + "paperPartCut": true, + "pdf417Code": true, + "pulseBel": true, + "pulseStandard": true, + "qrCode": true, + "starCommands": false + }, + "fonts": { + "0": { + "columns": 48, + "name": "Font A" + }, + "1": { + "columns": 64, + "name": "Font B" + }, + "2": { + "columns": 72, + "name": "Font C" + } + }, + "media": { + "width": { + "mm": 80, + "pixels": 640 + } + }, + "name": "CT-S651", + "notes": "Citizen CT-S651 profile. This is a two-color thermal printer, supporting paper sizes from 58mm up to 83mm\n", + "vendor": "Citizen" + }, "NT-5890K": { "codePages": { "0": "CP437", @@ -781,6 +889,91 @@ "notes": "POS-5890 thermal printer series, also marketed under various other names.\n", "vendor": "Zjiang" }, + "RP326": { + "codePages": { + "0": "CP437", + "1": "Unknown", + "2": "CP850", + "3": "CP860", + "4": "CP863", + "5": "CP865", + "6": "CP1251", + "7": "CP866", + "8": "Unknown", + "9": "Unknown", + "10": "Unknown", + "15": "CP862", + "16": "CP1252", + "17": "CP1253", + "18": "CP852", + "19": "CP858", + "20": "Unknown", + "21": "Unknown", + "22": "Unknown", + "23": "ISO_8859-1", + "24": "CP737", + "25": "CP1257", + "26": "Unknown", + "27": "CP720", + "28": "CP855", + "29": "CP857", + "30": "CP1250", + "31": "CP775", + "32": "CP1254", + "33": "CP1255", + "34": "CP1256", + "35": "CP1258", + "36": "ISO_8859-2", + "37": "ISO_8859-3", + "38": "ISO_8859-4", + "39": "ISO_8859-5", + "40": "ISO_8859-6", + "41": "ISO_8859-7", + "42": "ISO_8859-8", + "43": "ISO_8859-9", + "44": "ISO_8859-15", + "45": "Unknown", + "46": "CP856", + "47": "CP874" + }, + "colors": { + "0": "black" + }, + "features": { + "barcodeA": true, + "barcodeB": true, + "bitImageColumn": true, + "bitImageRaster": true, + "graphics": false, + "highDensity": true, + "paperFullCut": true, + "paperPartCut": true, + "pdf417Code": true, + "pulseBel": false, + "pulseStandard": true, + "qrCode": true, + "starCommands": false + }, + "fonts": { + "0": { + "columns": 42, + "name": "Font A" + }, + "1": { + "columns": 56, + "name": "Font B" + } + }, + "media": { + "width": { + "mm": "Unknown", + "pixels": "Unknown" + } + }, + "name": "RP326", + "notes": "", + "vendor": "Rongta" + }, "SP2000": { "codePages": { "0": "CP437", @@ -871,6 +1064,65 @@ "notes": "Star SP2000 impact printer series with ESC/POS emulation enabled", "vendor": "Star Micronics" }, + "Sunmi-V2": { + "codePages": { + "0": "CP437", + "2": "CP850", + "3": "CP860", + "4": "CP863", + "5": "CP865", + "13": "CP857", + "14": "CP737", + "15": "ISO_8859-7", + "16": "CP1252", + "17": "CP866", + "18": "CP852", + "19": "CP858", + "21": "CP874", + "33": "CP775", + "34": "CP855", + "36": "CP862", + "37": "CP864", + "254": "CP855" + }, + "colors": { + "0": "black" + }, + "features": { + "barcodeA": true, + "barcodeB": true, + "bitImageColumn": false, + "bitImageRaster": true, + "graphics": false, + "highDensity": true, + "paperFullCut": false, + "paperPartCut": false, + "pdf417Code": true, + "pulseBel": false, + "pulseStandard": true, + "qrCode": true, + "starCommands": false + }, + "fonts": { + "0": { + "columns": 32, + "name": "Font A" + }, + "1": { + "columns": 42, + "name": "Font B" + } + }, + "media": { + "width": { + "mm": 57.5, + "pixels": 384 + } + }, + "name": "Sunmi V2", + "notes": "Sunmi mini-POS Android device with a built-in Virtual Bluetooth thermal printer.\n", + "vendor": "Sunmi" + }, "TEP-200M": { "codePages": { "0": "CP437", @@ -1333,8 +1585,8 @@ }, "media": { "width": { - "mm": "Unknown", - "pixels": "Unknown" + "mm": 80, + "pixels": 512 } }, "name": "TM-T88IV", @@ -1380,14 +1632,92 @@ }, "media": { "width": { - "mm": "Unknown", - "pixels": "Unknown" + "mm": 80, + "pixels": 512 } }, "name": "TM-T88IV South Asia", "notes": "Epson TM-T88IV profile (South Asia models)\n", "vendor": "Epson" }, + "TM-T88V": { + "codePages": { + "0": "CP437", + "1": "CP932", + "2": "CP850", + "3": "CP860", + "4": "CP863", + "5": "CP865", + "11": "CP851", + "12": "CP853", + "13": "CP857", + "14": "CP737", + "15": "ISO_8859-7", + "16": "CP1252", + "17": "CP866", + "18": "CP852", + "19": "CP858", + "30": "TCVN-3-1", + "31": "TCVN-3-2", + "32": "CP720", + "33": "CP775", + "34": "CP855", + "35": "CP861", + "36": "CP862", + "37": "CP864", + "38": "CP869", + "39": "ISO_8859-2", + "40": "ISO_8859-15", + "41": "CP1098", + "45": "CP1250", + "46": "CP1251", + "47": "CP1253", + "48": "CP1254", + "49": "CP1255", + "50": "CP1256", + "51": "CP1257", + "52": "CP1258", + "53": "RK1048", + "255": "Unknown" + }, + "colors": { + "0": "black" + }, + "features": { + "barcodeA": true, + "barcodeB": true, + "bitImageColumn": true, + "bitImageRaster": true, + "graphics": true, + "highDensity": true, + "paperFullCut": true, + "paperPartCut": true, + "pdf417Code": true, + "pulseBel": false, + "pulseStandard": true, + "qrCode": true, + "starCommands": false + }, + "fonts": { + "0": { + "columns": 42, + "name": "Font A" + }, + "1": { + "columns": 56, + "name": "Font B" + } + }, + "media": { + "width": { + "mm": 80, + "pixels": 512 + } + }, + "name": "TM-T88V", + "notes": "Epson TM-T88V profile\n", + "vendor": "Epson" + }, "TM-U220": { "codePages": { "0": "CP437" @@ -1611,6 +1941,52 @@ "notes": "Star TUP500 thermal printer series with ESC/POS emulation enabled", "vendor": "Star Micronics" }, + "ZJ-5870": { + "codePages": { + "0": "CP437", + "1": "CP932", + "2": "CP850", + "3": "CP860", + "4": "CP863", + "5": "CP865", + "16": "CP1252", + "17": "CP866", + "18": "CP852" + }, + "colors": { + "0": "black" + }, + "features": { + "barcodeA": false, + "barcodeB": false, + "bitImageColumn": true, + "bitImageRaster": true, + "graphics": false, + "highDensity": false, + "paperFullCut": false, + "paperPartCut": false, + "pdf417Code": false, + "pulseBel": false, + "pulseStandard": true, + "qrCode": false, + "starCommands": false + }, + "fonts": { + "0": { + "columns": 32, + "name": "Font A" + } + }, + "media": { + "width": { + "mm": 48, + "pixels": 384 + } + }, + "name": "ZJ-5870 Thermal Receipt Printer", + "notes": "ESC/POS Profile for ZiJiang ZJ-5870 Thermal Receipt Printer, which may be branded AGPtEK or Esky, and identifies itself as a POS-58 Thermal Printer on selftest. This profile is suitable for alphanumberic character mode, but is untested on Chinese character mode. (Change modes by holding down feed button during power-on until the mode LED turns off, then release immediately.)\n", + "vendor": "ZiJiang" + }, "default": { "codePages": { "0": "CP437", diff --git a/test/bootstrap.php b/test/bootstrap.php index 749629ac..8ef37753 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -3,13 +3,7 @@ ini_set('display_errors', 1); $composer_autoload = __DIR__ . "/../vendor/autoload.php"; -$standalone_autoload = __DIR__ . "/../autoload.php"; - -if (file_exists($composer_autoload)) { - require_once($composer_autoload); -} else { - require_once($standalone_autoload); -} +require_once($composer_autoload); /** * Used in many of the tests to to output known-correct diff --git a/test/integration/ExampleTest.php b/test/integration/ExampleTest.php index 6ba8e23e..4b11281c 100644 --- a/test/integration/ExampleTest.php +++ b/test/integration/ExampleTest.php @@ -1,7 +1,7 @@ outpTest($outp, "pdf417-code.bin"); } + /** + * @medium + */ + public function testUnifontPrintBuffer() + { + $this->markTestSkipped('Not repeatable on Travis CI.'); + if(!file_exists("/usr/share/unifont/unifont.hex")) { + $this -> markTestSkipped("Test only repeatable w/ unifont installed"); + } + $outp = $this -> runExample("unifont-print-buffer.php"); + $this -> outpTest($outp, "unifont-print-buffer.bin"); + } + public function testInterfaceCups() { $outp = $this -> runSyntaxCheck("interface/cups.php"); diff --git a/test/integration/resources/output/character-encodings.bin b/test/integration/resources/output/character-encodings.bin index f93ea377..e5e6b5a8 100644 Binary files a/test/integration/resources/output/character-encodings.bin and b/test/integration/resources/output/character-encodings.bin differ diff --git a/test/integration/resources/output/unifont-print-buffer.bin b/test/integration/resources/output/unifont-print-buffer.bin new file mode 100644 index 00000000..ba163a8d Binary files /dev/null and b/test/integration/resources/output/unifont-print-buffer.bin differ diff --git a/test/unit/AuresCustomerDisplayTest.php b/test/unit/AuresCustomerDisplayTest.php index c0f803af..999adbad 100644 --- a/test/unit/AuresCustomerDisplayTest.php +++ b/test/unit/AuresCustomerDisplayTest.php @@ -4,7 +4,7 @@ use Mike42\Escpos\PrintConnectors\DummyPrintConnector; use Mike42\Escpos\CapabilityProfile; -class AuresCustomerDisplayTest extends PHPUnit_Framework_TestCase +class AuresCustomerDisplayTest extends PHPUnit\Framework\TestCase { protected $printer; protected $outputConnector; diff --git a/test/unit/CapabilityProfileTest.php b/test/unit/CapabilityProfileTest.php index 923811e7..f82a6ee4 100644 --- a/test/unit/CapabilityProfileTest.php +++ b/test/unit/CapabilityProfileTest.php @@ -1,7 +1,7 @@ setExpectedException('\InvalidArgumentException', 'simple'); + $this->expectException(InvalidArgumentException::class); $profile = CapabilityProfile::load('simpel'); } public function testBadFeatureNameSuggestion() { - $this->setExpectedException('\InvalidArgumentException', 'graphics'); + $this->expectException(InvalidArgumentException::class); $profile = CapabilityProfile::load('default'); $profile->getFeature('graphicx'); } diff --git a/test/unit/CodePageTest.php b/test/unit/CodePageTest.php index 0e7b661f..570bb4e1 100644 --- a/test/unit/CodePageTest.php +++ b/test/unit/CodePageTest.php @@ -1,39 +1,24 @@ markTestSkipped("Requires iconv"); - } - } - - public function testDataIconv() + public function testDataGenerated() { // Set up CP437 - $this->requiresIconv(); $cp = new CodePage("CP437", array( "name" => "CP437", "iconv" => "CP437" )); - $this->assertTrue($cp->isEncodable()); - $this->assertEquals($cp->getIconv(), "CP437"); - $this->assertEquals($cp->getName(), "CP437"); - $this->assertEquals($cp->getId(), "CP437"); - $this->assertEquals($cp->getNotes(), null); - // Get data and see if it's right - $data = $cp->getData(); - $expected = "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "; - $this->assertEquals($expected, $data); + $dataArray = $cp->getDataArray(); + $this->assertEquals(128, count($dataArray)); + $expected = "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσμτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "; + $this->assertEquals($expected, self::dataArrayToString($dataArray)); } - public function testDataIconvBogus() + public function testDataGenerateFailed() { // No errors raised, you just get an empty list of supported characters if you try to compute a fake code page - $this->requiresIconv(); $cp = new CodePage("foo", array( "name" => "foo", "iconv" => "foo" @@ -43,21 +28,49 @@ public function testDataIconvBogus() $this->assertEquals($cp->getName(), "foo"); $this->assertEquals($cp->getId(), "foo"); $this->assertEquals($cp->getNotes(), null); - $data = $cp->getData(); + $dataArray = $cp->getDataArray(); $expected = str_repeat(" ", 128); - $this->assertEquals($expected, $data); + $this->assertEquals($expected, self::dataArrayToString($dataArray)); // Do this twice (caching behaviour) - $data = $cp->getData(); - $this->assertEquals($expected, $data); + $dataArray = $cp->getDataArray(); + $this->assertEquals($expected, self::dataArrayToString($dataArray)); + } + + public function testDataDefined() + { + // A made up code page called "baz", which is the same as CP437 but with some unmapped values at the start. + $cp = new CodePage("baz", array( + "name" => "baz", + "iconv" => "baz", + "data" => [ + " âäàåçêëèïîìÄÅ", + "ÉæÆôöòûùÿÖÜ¢£¥₧ƒ", + "áíóúñѪº¿⌐¬½¼¡«»", + "░▒▓│┤╡╢╖╕╣║╗╝╜╛┐", + "└┴┬├─┼╞╟╚╔╩╦╠═╬╧", + "╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀", + "αßΓπΣσμτΦΘΩδ∞φε∩", + "≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "] + )); + $dataArray = $cp->getDataArray(); + $this->assertEquals(128, count($dataArray)); + $expected = " âäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσμτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "; + $this->assertEquals($expected, self::dataArrayToString($dataArray)); } public function testDataCannotEncode() { - $this->setExpectedException('\InvalidArgumentException'); + $this->expectException(InvalidArgumentException::class); $cp = new CodePage("foo", array( "name" => "foo" )); $this->assertFalse($cp->isEncodable()); - $cp->getData(); + $cp->getDataArray(); + } + + private static function dataArrayToString(array $codePoints) : string + { + // Assemble into character string so that the assertion is more compact + return implode(array_map("IntlChar::chr", $codePoints)); } -} \ No newline at end of file +} diff --git a/test/unit/CupsPrintConnectorTest.php b/test/unit/CupsPrintConnectorTest.php index 41499ee4..dec680b9 100644 --- a/test/unit/CupsPrintConnectorTest.php +++ b/test/unit/CupsPrintConnectorTest.php @@ -1,7 +1,7 @@ setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this->getMockConnector("FooPrinter", array("OtherPrinter")); $connector->expects($this->once())->method('getCmdOutput')->with($this->stringContains("lp -d 'FooPrinter' ")); $connector->finalize(); } public function testNoPrinter() { - $this -> setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this->getMockConnector("FooPrinter", array("")); } private function getMockConnector($path, array $printers) diff --git a/test/unit/EscposImageTest.php b/test/unit/EscposImageTest.php index 08e1be91..d4ad8b47 100644 --- a/test/unit/EscposImageTest.php +++ b/test/unit/EscposImageTest.php @@ -1,16 +1,16 @@ setExpectedException('Exception'); + $this -> expectException(Exception::class); $img = EscposImage::load('not-a-real-file.png'); } public function testImageNotSupportedException() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $img = EscposImage::load('/dev/null', false, array()); } } \ No newline at end of file diff --git a/test/unit/EscposPrintBufferTest.php b/test/unit/EscposPrintBufferTest.php index af0ee2b9..e978eef1 100644 --- a/test/unit/EscposPrintBufferTest.php +++ b/test/unit/EscposPrintBufferTest.php @@ -12,7 +12,7 @@ use Mike42\Escpos\Printer; use Mike42\Escpos\PrintConnectors\DummyPrintConnector; -class EscposPrintBufferTest extends PHPUnit_Framework_TestCase +class EscposPrintBufferTest extends PHPUnit\Framework\TestCase { protected $buffer; protected $outputConnector; @@ -39,6 +39,11 @@ protected function tearDown() $this -> outputConnector -> finalize(); } + public function testNotUtf8() { + $this -> expectException(Exception::class); + $this -> buffer -> writeText("Not valid UTF-8 can it be printed? \xc3\x28"); + } + public function testRawTextNonprintable() { $this -> buffer -> writeTextRaw("Test" . Printer::ESC . "v1\n"); diff --git a/test/unit/EscposTest.php b/test/unit/EscposTest.php index 0b70e96b..c12ffc5d 100644 --- a/test/unit/EscposTest.php +++ b/test/unit/EscposTest.php @@ -1,10 +1,10 @@ setExpectedException('Exception'); + $this -> expectException(Exception::class); } } @@ -51,12 +51,6 @@ public function testTextStringOutput() $this -> checkOutput("\x1b@The quick brown fox jumps over the lazy dog\n"); } - public function testTextDefault() - { - $this -> printer -> text(); - $this -> checkOutput("\x1b@"); - } - public function testTextChinese() { // Switch to chinese print mode, GBK output, switch back to alphanumeric. @@ -76,17 +70,8 @@ public function testTextString() { $this -> printer -> text("String"); $this -> printer -> text(123); - $this -> printer -> text(); - $this -> printer -> text(null); $this -> printer -> text(1.2); - $this -> printer -> text(new FooBar("FooBar")); - $this -> checkOutput("\x1b@String1231.2FooBar"); - } - - public function testTextObject() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> text(new DateTime()); + $this -> checkOutput("\x1b@String1231.2"); } public function testFeedDefault() @@ -103,19 +88,13 @@ public function testFeed3Lines() public function testFeedZero() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> feed(0); } - public function testFeedNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> feed("ab"); - } - public function testFeedTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> feed(256); } @@ -182,22 +161,16 @@ public function testSetUnderlineAcceptedValues() public function testSetUnderlineTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setUnderline(3); } public function testSetUnderlineNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setUnderline(-1); } - public function testSetUnderlineNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setUnderline("Hello"); - } - /* Emphasis */ public function testSetEmphasisDefault() { @@ -217,12 +190,6 @@ public function testSetEmphasisOff() $this -> checkOutput("\x1b@\x1bE\x00"); } - public function testSetEmphasisNonBoolean() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setEmphasis(7); - } - /* Double strike */ public function testSetDoubleStrikeDefault() { @@ -242,12 +209,6 @@ public function testSetDoubleStrikeOff() $this -> checkOutput("\x1b@\x1bG\x00"); } - public function testSetDoubleStrikeNonBoolean() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setDoubleStrike(4); - } - /* Font */ public function testSetFontDefault() { @@ -265,23 +226,17 @@ public function testSetFontAcceptedValues() public function testSetFontNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setFont(-1); } public function testSetFontTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setFont(3); } - public function testSetFontNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setFont('hello'); - } - /* Justification */ public function testSetJustificationDefault() { @@ -309,23 +264,17 @@ public function testSetJustificationCenter() public function testSetJustificationNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setJustification(-1); } public function testSetJustificationTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setFont(3); } - public function testSetJustificationNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setJustification('hello'); - } - /* Reverse feed */ public function testFeedReverseDefault() { @@ -341,22 +290,16 @@ public function testFeedReverse3() public function testFeedReverseNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> feedReverse(-1); } public function testFeedReverseTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> feedReverse(256); } - public function testFeedReverseNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> feedReverse('hello'); - } - /* Cut */ public function testCutDefault() { @@ -381,22 +324,16 @@ public function testBarcodeHeight10() public function testSetBarcodeHeightNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeHeight(-1); } public function testSetBarcodeHeightTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeHeight(256); } - public function testSetBarcodeHeightNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setBarcodeHeight('hello'); - } - /* Set barcode width */ public function testSetBarcodeWidthDefault() { @@ -412,21 +349,15 @@ public function testBarcodeWidth1() public function testSetBarcodeWidthNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeWidth(-1); } public function testSetBarcodeWidthTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeWidth(256); } - - public function testSetBarcodeWidthNonInteger() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setBarcodeWidth('hello'); - } /* Barcode text position */ public function testSetBarcodeTextPositionDefault() @@ -449,19 +380,19 @@ public function testSetBarcodeTextPositionBoth() public function testSetBarcodeTextPositionNegative() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeTextPosition(-1); } public function testSetBarcodeTextPositionTooLarge() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeTextPosition(4); } public function tesSetBarcodeTextPositionNonInteger() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setBarcodeTextPosition('hello'); } @@ -480,13 +411,13 @@ public function testBarcodeUpcaNumeric12Char() public function testBarcodeUpcaNumeric13Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("0123456789012", Printer::BARCODE_UPCA); } public function testBarcodeUpcaNonNumeric12Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("A12345678901", Printer::BARCODE_UPCA); } @@ -523,13 +454,13 @@ public function testBarcodeUpceNumeric12Char() public function testBarcodeUpceNumeric9Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("012345678", Printer::BARCODE_UPCE); } public function testBarcodeUpceNonNumeric12Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("A12345678901", Printer::BARCODE_UPCE); } @@ -548,13 +479,13 @@ public function testBarcodeJan13Numeric13Char() public function testBarcodeJan13Numeric11Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("01234567890", Printer::BARCODE_JAN13); } public function testBarcodeJan13NonNumeric13Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("A123456789012", Printer::BARCODE_JAN13); } @@ -573,13 +504,13 @@ public function testBarcodeJan8Numeric8Char() public function testBarcodeJan8Numeric9Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("012345678", Printer::BARCODE_JAN8); } public function testBarcodeJan8NonNumeric8Char() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("A1234567", Printer::BARCODE_JAN8); } @@ -610,25 +541,25 @@ public function testBarcodeCode39Asterisks() public function testBarcodeCode39AsterisksUnmatched() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("*TEXT", Printer::BARCODE_CODE39); } public function testBarcodeCode39AsteriskInText() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("12*34", Printer::BARCODE_CODE39); } public function testBarcodeCode39Lowercase() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("abcd", Printer::BARCODE_CODE39); } public function testBarcodeCode39Empty() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("**", Printer::BARCODE_CODE39); } @@ -641,13 +572,13 @@ public function testBarcodeItfNumericEven() public function testBarcodeItfNumericOdd() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("123", Printer::BARCODE_ITF); } public function testBarcodeItfNonNumericEven() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("A234", Printer::BARCODE_ITF); } @@ -666,13 +597,13 @@ public function testBarcodeCodabarSpecialChars() public function testBarcodeCodabarNotWrapped() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("012345", Printer::BARCODE_CODABAR); } public function testBarcodeCodabarStartStopWrongPlace() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("012A45", Printer::BARCODE_CODABAR); } @@ -685,7 +616,7 @@ public function testBarcodeCode93Valid() public function testBarcodeCode93Empty() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("", Printer::BARCODE_CODE93); } @@ -710,7 +641,7 @@ public function testBarcodeCode128ValidC() public function testBarcodeCode128NoCodeSet() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> barcode("ABCD", Printer::BARCODE_CODE128); } @@ -741,22 +672,16 @@ function testPulseOddMs() function testPulseTooHigh() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> pulse(0, 512, 2); } function testPulseTooLow() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> pulse(0, 0, 2); } - - function testPulseNotANumber() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> pulse("fish"); - } - + /* Set reverse */ public function testSetReverseColorsDefault() { @@ -776,12 +701,6 @@ public function testSetReverseColorsOff() $this -> checkOutput("\x1b@\x1dB\x00"); } - public function testSetReverseColorsNonBoolean() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> setReverseColors(7); - } - /* Bit image print */ public function testBitImageBlack() { @@ -896,8 +815,8 @@ public function testPdf417CodeEmpty() public function testPdf417CodeNotSupported() { - $this -> setExpectedException('Exception'); - $profile = SimpleCapabilityProfile::getInstance(); + $this -> expectException(Exception::class); + $profile = CapabilityProfile::load("simple"); $this -> printer = new Printer($this -> outputConnector, $profile); $this -> printer -> pdf417Code("1234"); } @@ -917,16 +836,10 @@ public function testPdf417CodeChangeErrorCorrection() public function testPdf417CodeChangeErrorCorrectionOutOfRange() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> pdf417Code("1234", 3, 3, 0, 5.0); } - public function testPdf417CodeChangeErrorCorrectionInvalid() - { - $this -> setExpectedException('InvalidArgumentException'); - $this -> printer -> pdf417Code("1234", 3, 3, 0, "Foobar"); - } - public function testPdf417CodeChangeOption() { // Use the alternate truncated format @@ -1014,7 +927,7 @@ public function testSetTextSizeLarge() public function testSetTextSizeInvalid() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setTextSize(0, 9); } @@ -1033,7 +946,7 @@ public function testSetColorAlternative() public function testSetColorInvalid() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setColor(3); } @@ -1046,7 +959,7 @@ public function testSetLineSpacingDefault() public function testSetLineSpacingInvalid() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setLineSpacing(300); } @@ -1077,7 +990,7 @@ public function testSetPrintWidthNarrow() public function testSetPrintWidthInvalid() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setPrintWidth(0); } @@ -1096,7 +1009,7 @@ public function testSetPrintLeftMarginWide() public function testPrintLeftMarginInvalid() { - $this -> setExpectedException('InvalidArgumentException'); + $this -> expectException(InvalidArgumentException::class); $this -> printer -> setPrintLeftMargin(70000); $this -> checkOutput(); } @@ -1108,20 +1021,3 @@ public function testSetUpsideDown() $this -> checkOutput("\x1b@\x1b{\x01"); } } - -/* - * For testing that string-castable objects are handled - */ -class FooBar -{ - private $foo; - public function __construct($foo) - { - $this -> foo = $foo; - } - - public function __toString() - { - return $this -> foo; - } -} diff --git a/test/unit/Experimental/Unifont/UnifontPrintBufferTest.php b/test/unit/Experimental/Unifont/UnifontPrintBufferTest.php new file mode 100644 index 00000000..a4801612 --- /dev/null +++ b/test/unit/Experimental/Unifont/UnifontPrintBufferTest.php @@ -0,0 +1,49 @@ + outputConnector = new DummyPrintConnector(); + $this -> printer = new Printer($this -> outputConnector); + $filename = tempnam(sys_get_temp_dir(), "escpos-php-"); + $glyphs = [ + "0020:00000000000000000000000000000000", // space is guessed + "0041:0000000018242442427E424242420000" // Letter "A" from Wikipedia + ]; + file_put_contents($filename, implode("\n", $glyphs)); + $printBuffer = new UnifontPrintBuffer($filename); + $this -> printer -> setPrintBuffer($printBuffer); + } + + protected function checkOutput($expected = null) + { + /* Check those output strings */ + $outp = $this -> outputConnector -> getData(); + if ($expected === null) { + echo "\nOutput was:\n\"" . friendlyBinary($outp) . "\"\n"; + } + $this -> assertEquals($expected, $outp); + } + + protected function tearDown() + { + $this -> outputConnector -> finalize(); + } + + public function testString() + { + // Render the text "AA A" rendered via used-defined font. + $this -> printer -> text("AA A\r\n"); + $this -> checkOutput("\x1b@\x1b!1\x1b%\x01\x1b&\x03 \x08\x00\x00\x00\x01\xfc\x00\x06@\x00\x08@\x00\x08@\x00\x06@\x00\x01\xfc\x00\x00\x00\x00 \x1b&\x03!!\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00! \x0a"); + } +} diff --git a/test/unit/FilePrintConnectorTest.php b/test/unit/FilePrintConnectorTest.php index 63728717..f8e344cf 100644 --- a/test/unit/FilePrintConnectorTest.php +++ b/test/unit/FilePrintConnectorTest.php @@ -1,7 +1,7 @@ finalize(); $connector -> finalize(); // Silently do nothing if printer already closed + $this -> assertEquals("", file_get_contents($tmpfname)); unlink($tmpfname); } public function testReadAfterClose() { // Should attempt to send data to the local printer by writing to it - $this -> setExpectedException('Exception'); + $this -> expectException(Exception::class); $tmpfname = tempnam("/tmp", "php"); $connector = new FilePrintConnector($tmpfname); $connector -> finalize(); diff --git a/test/unit/GdEscposImageTest.php b/test/unit/GdEscposImageTest.php index da755f7b..2a093fd2 100644 --- a/test/unit/GdEscposImageTest.php +++ b/test/unit/GdEscposImageTest.php @@ -2,7 +2,7 @@ use Mike42\Escpos\GdEscposImage; use Mike42\Escpos\EscposImage; -class GdEscposImageTest extends PHPUnit_Framework_TestCase +class GdEscposImageTest extends PHPUnit\Framework\TestCase { /** @@ -11,7 +11,7 @@ class GdEscposImageTest extends PHPUnit_Framework_TestCase */ public function testGdBadFilename() { - $this -> setExpectedException('Exception'); + $this -> expectException(Exception::class); $this -> loadAndCheckImg('not a real file.png', 1, 1, null, null); } diff --git a/test/unit/ImagickEscposImageTest.php b/test/unit/ImagickEscposImageTest.php index 76831f76..f6743c77 100644 --- a/test/unit/ImagickEscposImageTest.php +++ b/test/unit/ImagickEscposImageTest.php @@ -2,7 +2,7 @@ use Mike42\Escpos\ImagickEscposImage; use Mike42\Escpos\EscposImage; -class ImagickEscposImageTest extends PHPUnit_Framework_TestCase +class ImagickEscposImageTest extends PHPUnit\Framework\TestCase { /** @@ -11,7 +11,7 @@ class ImagickEscposImageTest extends PHPUnit_Framework_TestCase */ public function testImagickBadFilename() { - $this -> setExpectedException('Exception'); + $this -> expectException(Exception::class); $this -> loadAndCheckImg('not a real file.png', 1, 1, null, null); } @@ -85,7 +85,7 @@ public function testPdfAllPages() public function testPdfBadFilename() { - $this -> setExpectedException('Exception'); + $this -> expectException(Exception::class); $this -> loadAndCheckPdf('not a real file', 1, 1, array(), array()); } diff --git a/test/unit/LegacyCapabilityProfileTest.php b/test/unit/LegacyCapabilityProfileTest.php deleted file mode 100644 index 360dee90..00000000 --- a/test/unit/LegacyCapabilityProfileTest.php +++ /dev/null @@ -1,79 +0,0 @@ - profiles = array( - 'Mike42\Escpos\CapabilityProfiles\DefaultCapabilityProfile', - 'Mike42\Escpos\CapabilityProfiles\EposTepCapabilityProfile', - 'Mike42\Escpos\CapabilityProfiles\SimpleCapabilityProfile', - 'Mike42\Escpos\CapabilityProfiles\StarCapabilityProfile', - 'Mike42\Escpos\CapabilityProfiles\P822DCapabilityProfile'); - $this -> checklist = array(); - foreach ($this -> profiles as $profile) { - $this-> checklist[] = $profile::getInstance(); - } - } - - function testSupportedCodePages() - { - foreach ($this -> checklist as $obj) { - $check = $obj -> getCodePages(); - $this -> assertTrue(is_array($check) && isset($check[0])); - foreach ($check as $num => $page) { - $this -> assertTrue(is_numeric($num)); - } - } - } - - function testText() { - /* Smoke test over text rendering with each profile. - * Just makes sure we can attempt to print 'hello world' and a non-ASCII - * char without anything blowing up */ - foreach ($this -> checklist as $obj) { - $connector = new DummyPrintConnector(); - $printer = new Printer($connector, $obj); - $printer -> text("Hello world €\n"); - $printer -> close(); - // Check for character cache - $profileName = $obj -> getId(); - $expected = "Characters-$profileName.ser.z"; - $filename = __DIR__ . "/../../src/Mike42/Escpos/PrintBuffers/cache/$expected"; - $this -> assertFileExists($filename); - } - } - - function testSupportsBitImageRaster() - { - foreach ($this -> checklist as $obj) { - $check = $obj -> getSupportsBitImageRaster(); - $this -> assertTrue(is_bool($check)); - } - } - - function testSupportsGraphics() - { - foreach ($this -> checklist as $obj) { - $check = $obj -> getSupportsGraphics(); - $this -> assertTrue(is_bool($check)); - } - } - - function testSupportsQrCode() - { - foreach ($this -> checklist as $obj) { - $check = $obj -> getSupportsQrCode(); - $this -> assertTrue(is_bool($check)); - } - } -} diff --git a/test/unit/MultiplePrintConnectorTest.php b/test/unit/MultiplePrintConnectorTest.php new file mode 100644 index 00000000..0508c97a --- /dev/null +++ b/test/unit/MultiplePrintConnectorTest.php @@ -0,0 +1,27 @@ +text("Hello World\n"); + $printer->cut(); + // Get data out and close the printer + $kitchenText = $kitchenPrinter->getData(); + $barText = $barPrinter->getData(); + $printer->close(); + // Should have matching prints to each printer + $this->assertEquals("\x1b@Hello World\x0a\x1dVA\x03", $kitchenText); + $this->assertEquals("\x1b@Hello World\x0a\x1dVA\x03", $barText); + } +} diff --git a/test/unit/NativeEscposImageTest.php b/test/unit/NativeEscposImageTest.php new file mode 100644 index 00000000..3c6440b7 --- /dev/null +++ b/test/unit/NativeEscposImageTest.php @@ -0,0 +1,99 @@ + expectException(Exception::class); + $this -> loadAndCheckImg('not a real file.png', 1, 1, null, null); + } + + /** + * @medium + */ + public function testBlack() + { + foreach (array('bmp', 'gif', 'png') as $format) { + $this -> loadAndCheckImg('canvas_black.' . $format, 1, 1, "\x80", array("\x80")); + } + } + + /** + * @medium + */ + public function testBlackTransparent() + { + foreach (array('gif', 'png') as $format) { + $this -> loadAndCheckImg('black_transparent.' . $format, 2, 2, "\xc0\x00", array("\x80\x80")); + } + } + + /** + * @medium + */ + public function testBlackWhite() + { + foreach (array('bmp', 'png', 'gif') as $format) { + $this -> loadAndCheckImg('black_white.' . $format, 2, 2, "\xc0\x00", array("\x80\x80")); + } + } + + /** + * @medium + */ + public function testBlackWhiteTall() + { + // We're very interested in correct column format chopping here at 8 pixels + $this -> loadAndCheckImg('black_white_tall.png', 2, 16, + "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x00\x00\x00\x00\x00\x00\x00\x00", array("\xff\xff", "\x00\x00")); + } + + /** + * @medium + */ + public function testWhite() + { + foreach (array('bmp', 'png', 'gif') as $format) { + $this -> loadAndCheckImg('canvas_white.' . $format, 1, 1, "\x00", array("\x00")); + } + } + + /** + * Load an EscposImage and run a check. + */ + private function loadAndCheckImg($fn, $width, $height, $rasterFormat = null, $columnFormat = null) + { + $onDisk = ($fn === null ? null : (dirname(__FILE__) . "/resources/$fn")); + // With optimisations + $imgOptimised = new NativeEscposImage($onDisk, true); + $this -> checkImg($imgOptimised, $width, $height, $rasterFormat, $columnFormat); + // ... and without + $imgUnoptimised = new NativeEscposImage($onDisk, false); + $this -> checkImg($imgUnoptimised, $width, $height, $rasterFormat, $columnFormat); + } + + /** + * Check image against known width, height, output. + */ + private function checkImg(EscposImage $img, $width, $height, $rasterFormatExpected = null, $columnFormatExpected = null) + { + $rasterFormatActual = $img -> toRasterFormat(); + $columnFormatActual = $img -> toColumnFormat(); + if ($rasterFormatExpected === null) { + echo "\nImage was: " . $img -> getWidth() . "x" . $img -> getHeight() . ", raster data \"" . friendlyBinary($rasterFormatActual) . "\""; + } + if ($columnFormatExpected === null) { + echo "\nImage was: " . $img -> getWidth() . "x" . $img -> getHeight() . ", column data \"" . friendlyBinary($columnFormatActual) . "\""; + } + $this -> assertEquals($height , $img -> getHeight()); + $this -> assertEquals($width, $img -> getWidth()); + $this -> assertEquals($rasterFormatExpected, $rasterFormatActual, "Raster format did not match expected"); + $this -> assertEquals($columnFormatExpected, $columnFormatActual, "Column format did not match expected"); + } +} diff --git a/test/unit/UriPrintConnectorTest.php b/test/unit/UriPrintConnectorTest.php index 715dd8d7..c8287e79 100644 --- a/test/unit/UriPrintConnectorTest.php +++ b/test/unit/UriPrintConnectorTest.php @@ -1,7 +1,8 @@ expectException(Notice::class); $connector = UriPrintConnector::get("smb://windows/printer"); $this -> assertEquals('Mike42\Escpos\PrintConnectors\WindowsPrintConnector', get_class($connector)); // We expect that this will throw an exception, we can't diff --git a/test/unit/WindowsPrintConnectorTest.php b/test/unit/WindowsPrintConnectorTest.php index 038c9c20..a2370ddb 100644 --- a/test/unit/WindowsPrintConnectorTest.php +++ b/test/unit/WindowsPrintConnectorTest.php @@ -1,7 +1,7 @@ setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this -> getMockConnector("LPT1", WindowsPrintConnector::PLATFORM_MAC); $connector -> expects($this -> exactly(0)) -> method('runWrite'); @@ -36,7 +36,7 @@ public function testLptMac() public function testLptLinux() { // Cannot print to local printer on Linux with this connector - $this -> setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this -> getMockConnector("LPT1", WindowsPrintConnector::PLATFORM_LINUX); $connector -> expects($this -> exactly(0)) -> method('runWrite'); @@ -64,7 +64,7 @@ public function testComWindows() public function testComMac() { // Cannot print to local printer on Mac with this connector - $this -> setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this -> getMockConnector("COM1", WindowsPrintConnector::PLATFORM_MAC); $connector -> expects($this -> exactly(0)) -> method('runWrite'); @@ -78,7 +78,7 @@ public function testComMac() public function testComLinux() { // Cannot print to local printer on Linux with this connector - $this -> setExpectedException('BadMethodCallException'); + $this -> expectException(BadMethodCallException::class); $connector = $this -> getMockConnector("COM1", WindowsPrintConnector::PLATFORM_LINUX); $connector -> expects($this -> exactly(0)) -> method('runWrite'); @@ -160,7 +160,7 @@ public function testSharedPrinterWindowsUsernamePassword() public function testSharedPrinterMac() { // Not implemented - $this -> setExpectedException('Exception'); + $this -> expectException(Exception::class); $connector = $this -> getMockConnector("smb://Guest@example-pc/Printer", WindowsPrintConnector::PLATFORM_MAC); $connector -> expects($this -> exactly(0)) -> method('runWrite');