Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
php-versions: [ '8.3', '8.4' ]
composer-flags: [ '', '--prefer-lowest' ]
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -46,17 +46,17 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
php-version: 8.3
coverage: pcov

- name: Install dependencies
run: composer update --prefer-dist --no-progress --no-suggest --prefer-stable

- name: Run test suite
run: php -dpcov.enabled=1 -dpcov.exclude="~vendor~" vendor/bin/phpunit --testsuite unit --coverage-clover ./.coverage/coverage.xml
run: php -dpcov.enabled=1 -dpcov.exclude="~vendor~" vendor/bin/phpunit --testsuite unit --coverage-clover ./coverage.xml

- name: Check coverage
run: test ! -f ./.coverage/coverage.xml || php vendor/bin/phpfci inspect ./.coverage/coverage.xml ./.coverage/phpfci.xml --exit-code-on-failure
run: test ! -f ./.coverage/coverage.xml || php vendor/bin/phpfci inspect ./coverage.xml ./phpfci.xml --exit-code-on-failure

quality:
name: Quality checks
Expand All @@ -67,7 +67,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.3
coverage: none

- name: Install dependencies
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/.idea
/vendor
/composer.lock
/phpunit.xml
/.phpunit.result.cache
/.phpunit.cache
/composer.lock
/coverage.xml
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,93 @@
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.1-8892BF)](https://php.net/)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.3-8892BF)](https://php.net/)

# Digitalrevolution IPP library

## Installation

```bash
composer require digitalrevolution/ipp
```

## Usage

### Initialize the library

```php
$server = new IppServer();
$server->setUri('https://cups.local');
$server->setUsername('admin'); // optional
$server->setPassword('admin'); // optional

$ipp = new Ipp($server, new Psr18Client());
```

### Print a file

```php
// define a printer
$printer = new IppPrinter();
$printer->setHostname('my.printer');

// print a file on the selected printer
$ippFile = new IppPrintFile(file_get_contents('/dir/file.ps'), FileTypeEnum::PS);
$ipp->print($printer, $ippFile);
```

### Fetch job attributes

```php
$printJob = $ipp->print($printer, $ippFile);
$updatedPrintJob = $ipp->getJobAttributes($printJob->getJobUri());
```

### Register a printer with cups

```php
$printer = new IppPrinter();
$printer->setHostname('my.printer');
$printer->setDeviceUri('my.uri');
$printer->setLocation('location');

$ipp->createPrinter($printer);
```

### Delete a printer

```php
$printer = new IppPrinter();
$printer->setHostname('my.printer');

$ipp->deletePrinter($printer);
```

### Contributing

See [contributing.md](./CONTRIBUTING.md)
Pull requests welcome for adding standard IPP Operations

### Creating a custom IPP operation

This project is created to be easily extensible, adding a new IPP operation is as simple as making sure it has an identifier in IppOperationEnum
Then adding any Job, Printer or Operation Attributes as required by your standard.
Finally sending the request and parsing the response using the standard parser.

```php
public function myOperation(): IppResponseInterface
$operation = new IppOperation(IppOperationEnum::OperationType);
$operation->addOperationAttribute(new IppAttribute(IppTypeEnum::Charset, 'attributes-charset', 'utf-8'));

$response = $this->client->sendRequest(
new Request(
'POST',
$this->server->getUri(),
['Content-Type' => 'application/ipp'],
(string)$operation
)
);

return $this->parser->getResponse($response->getBody()->getContents());
}
```

## About us

Expand Down
57 changes: 40 additions & 17 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
{
"name": "digitalrevolution/skeleton",
"description": "Digital Revolution skeleton package",
"name": "digitalrevolution/ipp",
"description": "Digital Revolution IPP library",
"type": "library",
"license": "MIT",
"minimum-stability": "stable",
"config": {
"sort-packages": true,
"process-timeout": 0,
"allow-plugins": {
"phpstan/extension-installer": true
}
"phpstan/extension-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"digitalrevolution/php-codesniffer-baseline": true
},
"lock": false
},
"require": {
"php": ">=8.1"
"php": "^8.3",
"nyholm/psr7": "^1.8",
"psr/http-client": "^1.0",
"psr/log": "^3.0",
"digitalrevolution/utils": "^1.0"
},
"require-dev": {
"digitalrevolution/phpunit-file-coverage-inspection": "^v2.0.0",
"phpmd/phpmd": "^2.14",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^11.5 || ^12.0",
"digitalrevolution/accessorpair-constraint": "^v2.4.1",
"digitalrevolution/phpunit-file-coverage-inspection": "^3.0",
"digitalrevolution/php-codesniffer-baseline": "^1.1",
"phpmd/phpmd": "^2.12",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.9.1",
"phpstan/phpstan-phpunit": "^1.2.2",
"phpunit/phpunit": "^11.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.7",
"slevomat/coding-standard": "^8.16"
Expand All @@ -31,19 +40,33 @@
"@baseline:phpmd"
],
"baseline:phpstan": "phpstan --generate-baseline",
"baseline:phpmd": "phpmd src,tests xml phpmd.xml.dist --generate-baseline",
"baseline:phpmd": "phpmd src,tests xml phpmd.xml --generate-baseline",
"check": [
"@check:phpstan",
"@check:phpmd",
"@check:phpcs"
],
"check:phpstan": "phpstan analyse",
"check:phpmd": "phpmd src,tests text phpmd.xml.dist --suffixes php",
"check:phpmd": "phpmd src,tests text phpmd.xml --suffixes php",
"check:phpcs": "phpcs src tests",
"fix": "@fix:phpcbf",
"fix:phpcbf": "phpcbf src tests",
"test": "phpunit",
"test:integration": "phpunit --testsuite integration",
"test:unit": "phpunit --testsuite unit"
"test": "phpunit --testsuite unit",
"test:coverage": [
"phpunit --testsuite unit --coverage-clover coverage.xml",
"phpfci inspect coverage.xml --exit-code-on-failure"
],
"test:phpfci": "phpfci inspect coverage.xml --exit-code-on-failure"
},
"autoload": {
"psr-4": {
"DR\\Ipp\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"DR\\Ipp\\Tests\\Unit\\": "tests/Unit/",
"DR\\Ipp\\Tests\\": "tests/"
}
}
}
4 changes: 2 additions & 2 deletions phpcs.xml.dist → phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
</rule>
<rule ref="SlevomatCodingStandard.Complexity.Cognitive">
<properties>
<property name="warningThreshold" value="16"/>
<property name="errorThreshold" value="16"/>
<property name="warningThreshold" value="6"/>
<property name="errorThreshold" value="6"/>
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Arrays.DisallowImplicitArrayCreation"/>
Expand Down
1 change: 0 additions & 1 deletion phpfci.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpfci xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/digitalrevolution/phpunit-file-coverage-inspection/resources/phpfci.xsd"
min-coverage="100">
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ parameters:
treatPhpDocTypesAsCertain: false
paths:
- src
- test
- tests
File renamed without changes.
Empty file removed src/.gitkeep
Empty file.
58 changes: 58 additions & 0 deletions src/Client/CupsIppHttpClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace DR\Ipp\Client;

use DR\Ipp\Entity\IppServer;
use DR\Ipp\Entity\Response\IppResponseInterface;
use DR\Ipp\Enum\IppOperationEnum;
use DR\Ipp\Protocol\IppOperation;
use DR\Ipp\Protocol\IppResponseParserInterface;
use Nyholm\Psr7\Request;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;

class CupsIppHttpClient implements IppHttpClientInterface
{
public function __construct(
private readonly IppServer $server,
private readonly ClientInterface $client,
private readonly IppResponseParserInterface $parser
) {
}

/**
* @param IppOperation $operation
*
* @return IppResponseInterface
* @throws ClientExceptionInterface
*/
public function sendRequest(IppOperation $operation): IppResponseInterface
{
if ($operation->getOperation()->value >= IppOperationEnum::CupsGetDefault->value) {
$response = $this->client->sendRequest(
new Request(
'POST',
$this->server->getUri() . '/admin',
[
'Content-Type' => 'application/ipp',
'Authorization' => 'Basic ' . base64_encode($this->server->getUsername() . ":" . $this->server->getPassword())
],
(string)$operation
)
);
} else {
$response = $this->client->sendRequest(
new Request(
'POST',
$this->server->getUri(),
['Content-Type' => 'application/ipp'],
(string)$operation
)
);
}

return $this->parser->getResponse($response->getBody()->getContents());
}
}
17 changes: 17 additions & 0 deletions src/Client/IppHttpClientInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace DR\Ipp\Client;

use DR\Ipp\Entity\Response\IppResponseInterface;
use DR\Ipp\Protocol\IppOperation;
use Psr\Http\Client\ClientExceptionInterface;

interface IppHttpClientInterface
{
/**
* @throws ClientExceptionInterface
*/
public function sendRequest(IppOperation $operation): IppResponseInterface;
}
Loading