PHPackages                             civicrm/composer-compile-lib - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. civicrm/composer-compile-lib

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

civicrm/composer-compile-lib
============================

Small library of compilation helpers

v0.8(1y ago)4369.8k↓24.4%34MITPHP

Since Sep 30Pushed 1y ago16 watchersCompare

[ Source](https://github.com/civicrm/composer-compile-lib)[ Packagist](https://packagist.org/packages/civicrm/composer-compile-lib)[ RSS](/packages/civicrm-composer-compile-lib/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (5)Versions (9)Used By (4)

CiviCRM Composer Compilation Library
====================================

[](#civicrm-composer-compilation-library)

This package provides a handful of small tasks and helpers for use with [composer-compile-plugin](https://github.com/civicrm/composer-compile-plugin).

Design guidelines for this package:

- To ensure easy operation in a new/unbooted system:
    - Use basic functions and static methods
    - Use primitive data sources (such as static JSON files)
- To ensure that compilation steps report errors:
    - Every task/function must throw an exception if it doesn't work.
- To allow pithy tasks:
    - If a task is outputting to a folder, and if the folder doesn't exist, then it should auto-create the folder.

The primary purpose here is *demonstrative* - to provide examples. Consequently, it is fairly minimal / lightweight / loosely-coupled. There is no dependency on CiviCRM. Conversely, CiviCRM packages may define other tasks which are not in this library.

Require the library
-------------------

[](#require-the-library)

All the examples below require the `civicrm/composer-compile-lib` package. Load via CLI:

```
composer require civicrm/composer-compile-lib:'~0.2'
```

Or via `composer.json`:

```
  "require": {
    "civicrm/composer-compile-lib": "~0.2"
  }
```

Task: SCSS
----------

[](#task-scss)

In this example, we generate a file `dist/sandwich.css` by reading `scss/sandwich.scss`. The file may `@import` mixins and variables from the `./scss/` folder.

```
{
  "extra": {
    "compile": [
      {
        "title": "Prepare CSS (sandwich.css, salad.css)",
        "run": "@php-method \\CCL\\Tasks::scss",
        "watch-files": ["scss"],
        "scss-files": {
          "dist/sandwich.css": "scss/sandwich.scss",
          "dist/salad.css": "scss/salad.scss"
        },
        "scss-imports": ["scss"]
        "scss-import-prefixes": {"LOGICAL_PREFIX/": "physical/folder/"}
      }
    ]
  }
}
```

Note that a "task" simply calls a static PHP method (`@php-method \\CCL\\Tasks::scss`) with the JSON data as input. You can also call the method in a PHP script. For example, we could define a task based on a script:

```
{
  "extra": {
    "compile": [
      {
        "title": "Prepare CSS (sandwich.css, salad.css)",
        "run": "@php-script bin/compile-scss"
      }
    ]
  }
}
```

The following script generalizes the example from before -- it maps *any* SCSS files (`scss/*.scss`) to corresponding CSS files (`dist/#1.css`). This file-list is passed into `\CCL\Tasks::scss` for processing:

```
\CCL::assertTask();

$files = \CCL::globMap('scss/*.scss', 'dist/#1.css', 1);
\CCL\Tasks::scss([
  'scss-files' => $files,
  'scss-imports' => ['scss']
  'scss-import-prefixes' => ['LOGICAL_PREFIX/' => 'physical/folder/']
]);
```

Note that this implementation of `\CCL\Tasks::scss()` is fairly opinionated - it combines `scssphp` with `php-autoprefixer`. The output is written as two files, a larger files (`*.css`) and a smaller file (`*.min.css`).

Task: PHP Template
------------------

[](#task-php-template)

In this example, we use a PHP template to generate another PHP file. Specifically, we create `Sandwich.php` using the specification from [`Sandwich.json`](tests/examples/Sandwich.json) and [`EntityTemplate.php`](tests/examples/EntityTemplate.php):

```
{
  "extra": {
    "compile": [
      {
        "title": "Sandwich (src/Sandwich.php)",
        "run": "@php-method \\CCL\\Tasks::template",
        "watch-files": ["src/Entity"],
        "tpl-items": [
          "src/Entity/Sandwich.php": "src/Entity/Sandwich.json",
          "src/Entity/Salad.php": "src/Entity/Salad.json"
        ],
        "tpl-file": "src/Entity/EntityTemplate.php"
      }
    ]
  }
}
```

As in the previous example, the task is simply a PHP method (`@php-method \\CCL\\Tasks::template`), so it can be used from a PHP script. The following script would extend the pattern, mapping *any* JSON files (`src/Entity/*.json`) to corresponding PHP files (`src/Entity/#1.php`):

```
$files = \CCL::globMap('src/Entity/*.json', 'src/Entity/#1.php', 1);
\CCL\Tasks::template([
  "tpl-file" => "src/Entity/EntityTemplate.php",
  "tpl-items" => $files,
]);
```

Functions
---------

[](#functions)

PHP's standard library has a lot of functions that would work for basic file manipulation (`copy()`, `rename()`, `chdir()`, etc). The problem is error-signaling -- you have to explicitly check error-output, and this grows cumbersome for improvised glue code. It's more convenient to have a default *stop-on-error* behavior, e.g. throwing exceptions.

[symfony/filesystem](https://symfony.com/doc/current/components/filesystem.html) provides wrappers which throw exceptions. But it puts them into a class `Filesystem` which, which requires more boilerplate.

For the most part, `CCL` simply mirrors `symfony/filesystem` using static methods in the `CCL` class. Compare:

```
// PHP Standard Library
if (!copy('old', 'new')) {
  throw new \Exception("...");
}

// Symfony Filesystem
$fs = new \Symfony\Component\Filesystem\Filesystem();
$fs->copy('old', 'new');

// Composer Compile Library
\CCL::copy('old', 'new');
```

This is more convenient for scripting one-liners. For example, the following tasks do simple file operations. If anything goes wrong, they raise an exception and stop the compilation process.

```
{
  "extra": {
    "compile": [
      {
        "title": "Smorgasboard of random helpers",
        "run": [
          // Create files and folders
          "@php-eval \\CCL::dumpFile('dist/timestamp.txt', date('Y-m-d H:i:s'));",
          "@php-eval \\CCL::mkdir('some/other/place');",

          // Concatenate a few files
          "@php-eval \\CCL::dumpFile('dist/bundle.js', \\CCL::cat(glob('js/*.js'));",
          "@php-eval \\CCL::chdir('css'); \\CCL::dumpFile('all.css', ['colors.css', 'layouts.css']);",

          // If you need reference material from another package...
          "@export TWBS={{pkg:twbs/bootstrap}}",
          "@php-eval \\CCL::copy(getenv('TWBS') .'/dist/bootstrap.css', 'web/main.css')"
        ]
      }
    ]
  }
}
```

The full function list:

```
// CCL wrapper functions

function chdir(string $dir);
function glob($pat, $flags = null);

// CCL distinct functions

function cat($files);
function mapkv($array, $func);
function globMap($globPat, $mapPat, $flip = false);

// Symfony wrapper functions

function appendToFile($filename, $content);
function dumpFile($filename, $content);
function mkdir($dirs, $mode = 511);
function touch($files, $time = null, $atime = null);

function copy($originFile, $targetFile, $overwriteNewerFiles = true);
function mirror($originDir, $targetDir, $iterator = null, $options = []);
function remove($files);
function rename($origin, $target, $overwrite = false);

function chgrp($files, $group, $recursive = false);
function chmod($files, $mode, $umask = 0, $recursive = false);
function chown($files, $user, $recursive = false);

function hardlink($originFile, $targetFiles);
function readlink($path, $canonicalize = false);
function symlink($originDir, $targetDir, $copyOnWindows = false);

function exists($files);

function tempnam($dir, $prefix);
```

For more details about each function, see [`CCL\Functions`](src/Functions.php) and [symfony/filesystem](https://symfony.com/doc/current/components/filesystem.html).

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance31

Infrequent updates — may be unmaintained

Popularity41

Moderate usage in the ecosystem

Community24

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 87.9% 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

Every ~191 days

Recently: every ~323 days

Total

8

Last Release

719d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1336047?v=4)[Tim Otten](/maintainers/totten)[@totten](https://github.com/totten)

---

Top Contributors

[![totten](https://avatars.githubusercontent.com/u/1336047?v=4)](https://github.com/totten "totten (51 commits)")[![seamuslee001](https://avatars.githubusercontent.com/u/6799125?v=4)](https://github.com/seamuslee001 "seamuslee001 (3 commits)")[![demeritcowboy](https://avatars.githubusercontent.com/u/2967821?v=4)](https://github.com/demeritcowboy "demeritcowboy (2 commits)")[![jackrabbithanna](https://avatars.githubusercontent.com/u/1508311?v=4)](https://github.com/jackrabbithanna "jackrabbithanna (2 commits)")

### Embed Badge

![Health badge](/badges/civicrm-composer-compile-lib/health.svg)

```
[![Health](https://phpackages.com/badges/civicrm-composer-compile-lib/health.svg)](https://phpackages.com/packages/civicrm-composer-compile-lib)
```

###  Alternatives

[symplify/monorepo-builder

Not only Composer tools to build a Monorepo.

5205.3M82](/packages/symplify-monorepo-builder)[shyim/danger-php

Port of danger to PHP

8544.9k](/packages/shyim-danger-php)[mapbender/mapbender

Mapbender library

10117.4k5](/packages/mapbender-mapbender)[eliashaeussler/typo3-solver

Extension for TYPO3 CMS to extend TYPO3's exception handling with AI generated solutions

292.1k](/packages/eliashaeussler-typo3-solver)[numero2/contao-storelocator

Contao Plugin for managing stores (or in common address data) and providing a frontend-search based on geo data

121.5k](/packages/numero2-contao-storelocator)

PHPackages © 2026

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