-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Rob Gridley
committed
Jun 5, 2015
0 parents
commit 512a303
Showing
13 changed files
with
480 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.DS_Store | ||
/.idea | ||
/vendor | ||
/composer.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Rob Gridley <[email protected]> | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Zebra | ||
PHP ZPL builder and a basic client for network-connected Zebra label printers. | ||
|
||
Requires: PHP 5.6 with the GD module. | ||
|
||
* Create ZPL code in PHP that is clean and easy to read. | ||
* Convert images to ASCII hex bitmaps (JPEG, PNG, GIF, WBMP, and GD2 supported). | ||
* Simple wrapper for PHP sockets to send ZPL to the printer via raw TCP/IP (port 9100). | ||
|
||
## Examples | ||
The following example will print a label with an image positioned 50 dots from the top left. | ||
```php | ||
use Zebra\Client; | ||
use Zebra\Zpl\Image; | ||
use Zebra\Zpl\Builder; | ||
|
||
$zpl = new Builder(); | ||
$zpl->fo(50, 50); | ||
|
||
$image = new Image(file_get_contents('example.png')); | ||
$zpl->gf($image); | ||
|
||
$client = new Client('10.0.0.50'); | ||
$client->send($zpl); | ||
``` | ||
The same example using static constructors and method chaining: | ||
```php | ||
$image = new Image(file_get_contents('example.png')); | ||
$zpl = Zpl::start()->fo(50, 50)->gf($image); | ||
Client::printer('10.0.0.50')->send($zpl); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "robgridley/zebra", | ||
"description": "PHP ZPL builder and a basic client for network-connected Zebra label printers.", | ||
"require": { | ||
"php": ">=5.6.0" | ||
}, | ||
"require-dev": { | ||
"phpspec/phpspec": "~2.0" | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Rob Gridley", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"autoload": { | ||
"psr-4": { | ||
"Zebra\\": "src/" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
suites: | ||
acme_suite: | ||
namespace: Zebra | ||
psr4_prefix: Zebra |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php namespace spec\Zebra\Zpl; | ||
|
||
use Zebra\Zpl\Image; | ||
use Prophecy\Argument; | ||
use PhpSpec\ObjectBehavior; | ||
|
||
class BuilderSpec extends ObjectBehavior | ||
{ | ||
function it_is_initializable() | ||
{ | ||
$this->shouldHaveType('Zebra\Zpl\Builder'); | ||
} | ||
|
||
function it_creates_zpl_commands_with_string_number_and_boolean_parameters() | ||
{ | ||
$this->command('BC', 'N', 100, true)->__toString()->shouldReturn("^XA\n^BCN,100,Y\n^XZ"); | ||
} | ||
|
||
function it_creates_zpl_commands_from_magic_methods_and_their_arguments() | ||
{ | ||
$this->fo(50, 50)->__toString()->shouldReturn("^XA\n^FO50,50\n^XZ"); | ||
} | ||
|
||
function it_accepts_a_single_argument_of_image_for_gf_command(Image $image) | ||
{ | ||
$image->__toString()->willReturn("FF00"); | ||
$image->widthInBytes()->willReturn(2); | ||
$image->height()->willReturn(16); | ||
|
||
$this->gf($image)->__toString()->shouldReturn("^XA\n^GFA,32,32,2,FF00\n^XZ"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php namespace spec\Zebra\Zpl; | ||
|
||
use Prophecy\Argument; | ||
use PhpSpec\ObjectBehavior; | ||
|
||
class ImageSpec extends ObjectBehavior | ||
{ | ||
function let() | ||
{ | ||
$this->beConstructedWith(file_get_contents(__DIR__ . '/../test.png')); | ||
} | ||
|
||
function it_is_initializable() | ||
{ | ||
$this->shouldHaveType('Zebra\Zpl\Image'); | ||
} | ||
|
||
function it_converts_images_to_ascii_hexadecimal_bitmaps() | ||
{ | ||
$this->__toString()->shouldReturn('00400000400002E80003F80003F80013F9001BFB003FFF80FFFFE07FFFC03FFF801FFF000FFE0007FC000E4E00004000004000004000'); | ||
} | ||
|
||
function it_ignores_the_colour_palette_order_of_the_incoming_image() | ||
{ | ||
$this->beConstructedWith(file_get_contents(__DIR__ . '/../test.gif')); | ||
|
||
$this->__toString()->shouldReturn('FFBFE0FFBFE0FD17E0FC07E0FC07E0EC06E0E404E0C00060000000800020C00060E000E0F001E0F803E0F1B1E0FFBFE0FFBFE0FFBFE0'); | ||
} | ||
|
||
function it_gets_the_dimensions_of_the_image_in_pixels() | ||
{ | ||
$this->width()->shouldReturn(19); | ||
|
||
$this->height()->shouldReturn(18); | ||
} | ||
|
||
function it_gets_the_width_of_the_image_in_bytes() | ||
{ | ||
$this->widthInBytes()->shouldReturn(3); | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?php namespace Zebra; | ||
|
||
class Client | ||
{ | ||
/** | ||
* The endpoint. | ||
* | ||
* @var resource | ||
*/ | ||
protected $socket; | ||
|
||
/** | ||
* Create an instance. | ||
* | ||
* @param $host | ||
* @param int $port | ||
*/ | ||
public function __construct($host, $port = 9100) | ||
{ | ||
$this->connect($host, $port); | ||
} | ||
|
||
/** | ||
* Destroy an instance. | ||
*/ | ||
public function __destruct() | ||
{ | ||
$this->disconnect(); | ||
} | ||
|
||
/** | ||
* Create an instance statically. | ||
* | ||
* @param string $host | ||
* @param int $port | ||
* @return self | ||
*/ | ||
public static function printer($host, $port = 9100) | ||
{ | ||
return new static($host, $port); | ||
} | ||
|
||
/** | ||
* Connect to printer. | ||
* | ||
* @param string $host | ||
* @param int $port | ||
* @return bool | ||
*/ | ||
protected function connect($host, $port) | ||
{ | ||
$this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); | ||
|
||
if ( ! $this->socket || ! @socket_connect($this->socket, $host, $port)) { | ||
$error = $this->getLastError(); | ||
throw new ClientException($error['message'], $error['code']); | ||
} | ||
} | ||
|
||
/** | ||
* Close connection to printer. | ||
*/ | ||
protected function disconnect() | ||
{ | ||
@socket_close($this->socket); | ||
} | ||
|
||
/** | ||
* Send ZPL data to printer. | ||
* | ||
* @param string $zpl | ||
*/ | ||
public function send($zpl) | ||
{ | ||
if ( ! @socket_write($this->socket, $zpl)) { | ||
$error = $this->getLastError(); | ||
throw new ClientException($error['message'], $error['code']); | ||
} | ||
} | ||
|
||
/** | ||
* Get the last socket error. | ||
* | ||
* @return array | ||
*/ | ||
protected function getLastError() | ||
{ | ||
$code = socket_last_error($this->socket); | ||
$message = socket_strerror($code); | ||
|
||
return compact('code', 'message'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php namespace Zebra; | ||
|
||
use RuntimeException; | ||
|
||
class ClientException extends RuntimeException | ||
{ | ||
// | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?php namespace Zebra\Zpl; | ||
|
||
class Builder | ||
{ | ||
/** | ||
* ZPL commands. | ||
* | ||
* @var array | ||
*/ | ||
protected $zpl = array(); | ||
|
||
/** | ||
* Create a new instance statically. | ||
* | ||
* @return self | ||
*/ | ||
public static function start() | ||
{ | ||
return new static; | ||
} | ||
|
||
/** | ||
* Add a command. | ||
* | ||
* @param string $command | ||
* @param mixed $parameters,... | ||
* @return self | ||
*/ | ||
public function command($command, ...$parameters) | ||
{ | ||
$parameters = array_map([$this, 'convert'], $parameters); | ||
$this->zpl[] = '^' . strtoupper($command) . implode(',', $parameters); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Convert native types to their ZPL representations. | ||
* | ||
* @param mixed $parameter | ||
* @return mixed | ||
*/ | ||
protected function convert($parameter) | ||
{ | ||
if (is_bool($parameter)) { | ||
return $parameter ? 'Y' : 'N'; | ||
} | ||
|
||
return $parameter; | ||
} | ||
|
||
/** | ||
* Handle dynamic method calls. | ||
* | ||
* @param $method | ||
* @param $arguments | ||
* @return self | ||
*/ | ||
public function __call($method, $arguments) | ||
{ | ||
return $this->command($method, ...$arguments); | ||
} | ||
|
||
/** | ||
* Add GF command. | ||
* | ||
* @param mixed $parameters,... | ||
* @return self | ||
*/ | ||
public function gf(...$parameters) | ||
{ | ||
if (func_num_args() === 1 && ($image = $parameters[0]) instanceof Image) { | ||
|
||
$bytesPerRow = $image->widthInBytes(); | ||
$byteCount = $fieldCount = $bytesPerRow * $image->height(); | ||
|
||
return $this->command('GF', 'A', $byteCount, $fieldCount, $bytesPerRow, $image); | ||
} | ||
|
||
return $this->command('GF', ...$parameters); | ||
} | ||
|
||
/** | ||
* Convert instance to ZPL. | ||
* | ||
* @return string | ||
*/ | ||
public function toZpl() | ||
{ | ||
return implode("\n", array_merge(['^XA'], $this->zpl, ['^XZ'])); | ||
} | ||
|
||
/** | ||
* Convert instance to string. | ||
* | ||
* @return string | ||
*/ | ||
public function __toString() | ||
{ | ||
return $this->toZpl(); | ||
} | ||
|
||
} |
Oops, something went wrong.