PHPackages                             nacholibre/coffee-cups - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. nacholibre/coffee-cups

ActiveLibrary[HTTP &amp; Networking](/categories/http)

nacholibre/coffee-cups
======================

A simple PHP library for CUPS IPP (Internet Printing Protocol) communication

v0.1.0(7mo ago)1339↓82%MITPHPPHP ^8.1CI passing

Since Nov 27Pushed 3mo agoCompare

[ Source](https://github.com/nacholibre/coffee-cups)[ Packagist](https://packagist.org/packages/nacholibre/coffee-cups)[ RSS](/packages/nacholibre-coffee-cups/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (1)Versions (3)Used By (0)

☕ Coffee Cups
=============

[](#-coffee-cups)

A simple, modern PHP library for CUPS IPP (Internet Printing Protocol) communication with **zero dependencies**.

[![CI](https://github.com/nacholibre/coffee-cups/actions/workflows/ci.yml/badge.svg)](https://github.com/nacholibre/coffee-cups/actions/workflows/ci.yml)[![GitHub](https://camo.githubusercontent.com/c8f0d1cdd32008ad497978f97e2f21af174737546623f5b26dc53f8e129022a7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6e6163686f6c696272652f636f666665652d637570733f7374796c653d666c6174266c6f676f3d676974687562)](https://github.com/nacholibre/coffee-cups)[![PHP Version](https://camo.githubusercontent.com/04744bae0a61d2ffe29c26f07a9612eae20445fc6feaeb77b3af1f0e9be6447c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e312d3838393242462e737667)](https://php.net/)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](LICENSE)[![No Dependencies](https://camo.githubusercontent.com/4373869dba033bc855ef671f5bccbd2edb3867f87d51169ac7479d9edb896612/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646570656e64656e636965732d6e6f6e652d737563636573732e737667)](composer.json)

Features
--------

[](#features)

- 🖨️ Print documents to CUPS printers using IPP protocol
- 📋 Query printer status and capabilities
- 📄 Manage print jobs (cancel, hold, release)
- 🎯 Simple, fluent API for job configuration
- 🔐 Basic and digest authentication support
- 📦 **Zero dependencies** — only uses PHP's built-in cURL extension

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- cURL extension
- CUPS server

Installation
------------

[](#installation)

```
composer require nacholibre/coffee-cups
```

Quick Start
-----------

[](#quick-start)

### Print a File

[](#print-a-file)

```
use CoffeeCups\CupsClient;
use CoffeeCups\Job;

// Create a client (defaults to localhost:631)
$client = new CupsClient();

// Create and configure a print job
$job = new Job('My Document');
$job->setFile('/path/to/document.pdf')
    ->setCopies(2)
    ->setDuplex(true)
    ->setColor(true);

// Send to printer
$result = $client->print('HP_LaserJet', $job);

if ($result->isSuccessful()) {
    echo "Job ID: " . $result->getJobId();
}
```

### Print Raw Content

[](#print-raw-content)

```
use CoffeeCups\CupsClient;
use CoffeeCups\Job;

$client = new CupsClient();

$job = new Job('Receipt');
$job->setContent("Hello, World!\n\nThis is a test print.")
    ->setFormat('text/plain');

$result = $client->print('Receipt_Printer', $job);
```

Job Configuration
-----------------

[](#job-configuration)

The `Job` class provides a fluent API for configuring print jobs:

### Creating a Job

[](#creating-a-job)

```
// With name
$job = new Job('My Document');

// Without name (set later)
$job = new Job();
$job->setName('My Document');
```

### Document Source

[](#document-source)

```
// From file (auto-detects format from extension)
$job->setFile('/path/to/document.pdf');

// From raw content
$job->setContent($pdfContent);
```

### Document Format

[](#document-format)

```
$job->setFormat('application/pdf');      // PDF
$job->setFormat('application/postscript'); // PostScript
$job->setFormat('text/plain');           // Plain text
$job->setFormat('image/png');            // PNG image
```

### Copies

[](#copies)

```
$job->setCopies(3);
```

### Duplex (Two-Sided Printing)

[](#duplex-two-sided-printing)

```
$job->setDuplex(true);          // Two-sided, flip on long edge
$job->setDuplex(true, false);   // Two-sided, flip on short edge
$job->setDuplex(false);         // Single-sided
```

### Orientation

[](#orientation)

```
$job->setOrientation('portrait');
$job->setOrientation('landscape');
$job->setOrientation('reverse-portrait');
$job->setOrientation('reverse-landscape');
```

### Print Quality

[](#print-quality)

```
$job->setQuality('draft');    // Draft quality
$job->setQuality('normal');   // Normal quality
$job->setQuality('high');     // High quality
```

### Paper Size

[](#paper-size)

```
// Common shortcuts
$job->setMediaSize('a4');      // A4 paper
$job->setMediaSize('letter');  // US Letter
$job->setMediaSize('legal');   // US Legal
$job->setMediaSize('a3');      // A3 paper

// Full IPP media size names also work
$job->setMediaSize('iso_a4_210x297mm');
$job->setMediaSize('na_letter_8.5x11in');
```

### Media Type

[](#media-type)

```
$job->setMediaType('stationery');
$job->setMediaType('transparency');
$job->setMediaType('envelope');
```

### Color Mode

[](#color-mode)

```
$job->setColor(true);   // Color printing
$job->setColor(false);  // Monochrome/grayscale
```

### Job Priority

[](#job-priority)

```
$job->setPriority(75);  // 1-100, higher is more urgent
```

### Hold Job

[](#hold-job)

```
$job->setHold(true);   // Hold the job for later release
$job->setHold(false);  // Don't hold (default)
```

### Custom Attributes

[](#custom-attributes)

```
use CoffeeCups\Ipp\IppAttribute;

$job->addAttribute(IppAttribute::keyword('finishings', 'staple'));
$job->addAttribute(IppAttribute::integer('number-up', 4));
```

CupsClient API
--------------

[](#cupsclient-api)

### Connecting to CUPS

[](#connecting-to-cups)

```
use CoffeeCups\CupsClient;

// Local CUPS server
$client = new CupsClient();

// Remote server
$client = new CupsClient(
    host: 'print-server.local',
    port: 631,
    secure: false
);

// With authentication
$client = new CupsClient(
    host: 'print-server.local',
    username: 'admin',
    password: 'secret'
);
```

### Printing

[](#printing)

```
$result = $client->print('Printer_Name', $job);

if ($result->isSuccessful()) {
    echo "Job ID: " . $result->getJobId();
    echo "Job URI: " . $result->getJobUri();
} else {
    echo "Error: " . $result->getMessage();
}
```

### Printer Operations

[](#printer-operations)

```
// Get all printers
$printers = $client->getPrinters();

// Get specific printer
$printer = $client->getPrinter('HP_LaserJet');

echo $printer->name;
echo $printer->state;  // 'idle', 'processing', 'stopped'
echo $printer->isAcceptingJobs;

// Check capabilities
if ($printer->supportsColor()) {
    echo "Color printing supported";
}

if ($printer->supportsDuplex()) {
    echo "Duplex printing supported";
}

// Get default printer
$default = $client->getDefaultPrinter();
```

### Job Management

[](#job-management)

```
// Get jobs for a printer
$jobs = $client->getJobs('HP_LaserJet');

// Get only my jobs
$myJobs = $client->getJobs('HP_LaserJet', myJobs: true);

// Get completed jobs
$completed = $client->getJobs('HP_LaserJet', whichJobs: 'completed');

// Cancel a job
$client->cancelJob('HP_LaserJet', $jobId);

// Hold a job
$client->holdJob('HP_LaserJet', $jobId);

// Release a held job
$client->releaseJob('HP_LaserJet', $jobId);
```

### Printer Control

[](#printer-control)

```
// Pause printer
$client->pausePrinter('HP_LaserJet');

// Resume printer
$client->resumePrinter('HP_LaserJet');
```

Error Handling
--------------

[](#error-handling)

```
use CoffeeCups\CupsClient;
use CoffeeCups\Job;
use CoffeeCups\Exceptions\ConnectionException;
use CoffeeCups\Exceptions\IppException;

try {
    $client = new CupsClient();

    $job = new Job('Test');
    $job->setFile('/path/to/file.pdf');

    $result = $client->print('Printer_Name', $job);

    if (!$result->isSuccessful()) {
        echo "Print failed: " . $result->getMessage();
    }
} catch (ConnectionException $e) {
    echo "Connection failed: {$e->getMessage()}";
} catch (IppException $e) {
    echo "IPP error ({$e->getStatusCode()}): {$e->getMessage()}";
}
```

Printer URI Format
------------------

[](#printer-uri-format)

CUPS uses URIs to identify printers:

- `ipp://localhost:631/printers/Printer_Name` - IPP protocol
- `ipps://localhost:631/printers/Printer_Name` - IPP over TLS

The library handles URI construction automatically when you provide a printer name.

Testing
-------

[](#testing)

### Unit Tests

[](#unit-tests)

Run unit tests (no external dependencies required):

```
composer install
./vendor/bin/phpunit --testsuite unit
```

### Integration Tests

[](#integration-tests)

Integration tests run against a real CUPS server via Docker:

```
# Start CUPS server and run integration tests
make test-integration

# Or run everything via Docker
make test-all
```

You can also start the CUPS server manually:

```
# Start CUPS server (available at localhost:6631)
make cups-up

# Run integration tests
CUPS_HOST=localhost CUPS_PORT=6631 ./vendor/bin/phpunit --testsuite integration --group integration

# Stop CUPS server
make cups-down
```

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance73

Regular maintenance activity

Popularity17

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

210d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9cd8e289dcddefe2a8972b210d05a14d9465df0b5e9309b72387cbd022d093d9?d=identicon)[nacholibrev](/maintainers/nacholibrev)

---

Top Contributors

[![nacholibre](https://avatars.githubusercontent.com/u/1738437?v=4)](https://github.com/nacholibre "nacholibre (3 commits)")

---

Tags

printerprintprintingCUPSipp

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nacholibre-coffee-cups/health.svg)

```
[![Health](https://phpackages.com/badges/nacholibre-coffee-cups/health.svg)](https://phpackages.com/packages/nacholibre-coffee-cups)
```

###  Alternatives

[rawilk/laravel-printing

Direct printing for Laravel apps

564275.1k8](/packages/rawilk-laravel-printing)[illuminate/http

The Illuminate Http package.

11937.2M6.5k](/packages/illuminate-http)[rdkafka/rdkafka

A PHP extension for Kafka

2.2k20.0k1](/packages/rdkafka-rdkafka)[mezzio/mezzio-router

Router subcomponent for Mezzio

265.3M84](/packages/mezzio-mezzio-router)[php-aidc/label-printer

Easily create and print labels on various label printers

6023.6k](/packages/php-aidc-label-printer)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
