PHPackages                             kanopi/components - 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. kanopi/components

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

kanopi/components
=================

Kanopi Modular Component patterns for use in related PHP libraries, plugins, themes, and more

1.13.0(2y ago)15.5k↑46.7%[1 PRs](https://github.com/kanopi/kanopi-components/pulls)MITPHPPHP &gt;=8.0

Since Nov 14Pushed 2y ago4 watchersCompare

[ Source](https://github.com/kanopi/kanopi-components)[ Packagist](https://packagist.org/packages/kanopi/components)[ RSS](/packages/kanopi-components/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (7)Versions (39)Used By (0)

Kanopi Components Library
=========================

[](#kanopi-components-library)

PHP library to provide common model and service patterns for building other applications

Documentation Reference
-----------------------

[](#documentation-reference)

- [Definitions](#definitions)
- [Structure](#structure)
- [Code Quality](#code-quality)
- How To

Definitions
-----------

[](#definitions)

- **Entity** - Any structured model, class, interface, etc representing data flowing through the system. The model contains sets of data fields with free-form and indexed content. For instance, a Post Type or Node which represents a Location with a free-form Address and an indexed Region or State.
- **Entity Iterator** - PHP Iterator which takes a Class, Interface or Scalar type and validates each member entity is of the requested type
- **Indexed Entity** - Any entity which uses a numerical index, for instance, a Post Type in WordPress uses a Post ID, its index.
- **Indexed Group Entity** - Perhaps written in a grammatically incorrect way, this is a Group associated with an indexed entity, for instance a City/Region taxonomy associated with a Location
- **Reader** - Data repository which only allows reading
- **Repository** - Generic name for a place to store data, could be a CSV file, HTTP/S Endpoint, Database, etc.
- **Set** - A grouping of similar data, generally expected to be of the same entity in this system, enforced using Entity Iterators
- **Stream** - Flow of data between repositories, this system implements streams to read from source repositories and write to target repositories
- **Writer** - Data repository which allows reading/writing

Structure
---------

[](#structure)

All structures are stored under the PSR-4 namespace `Kanopi\Components`.

### Commands

[](#commands)

**Namespace**: `Kanopi\Components\Commands`

Group of commonly used CLI Commands available to register and use on WordPress, and in the future Drupal.

For WordPress, all commands are for WPCLI, and can be registered from this library by calling `Kanopi\Components\Commands\Registration::WPCLICommands()`.

### Logger

[](#logger)

**Namespace**: `Kanopi\Components\Logger`

`ILogger` is the interface to wrap and proxy different logging methods. Use a Multiplex to log to more than one Logger target at once.

### Model

[](#model)

**Namespace**: `Kanopi\Components\Model`

Data structures used by functional components, like Repositories and Services, provide patterns for Collections/Iterators with validity, Data Transformation, and Exceptions.

Provides a set of Exception classes for standard interactions, please add custom exceptions or use this depending on your use case.

### Processor

[](#processor)

**Namespace**: `Kanopi\Components\Processor`

Direct component to model an entire Import, Export, or other process. This exists to coordinate the efforts of multiple Repositories, Services, and Transformers. It will contain the business rules to govern how, when, and why data is transformed and stored in each Service or Repository component.

### Repositories

[](#repositories)

**Namespace**: `Kanopi\Components\Repositories`

Interfaces in front of direct I/O operations in the concrete classes. This namespace is intended to pattern interactions with direct sources like databases, files, etc.

This, along with Dependency Injection, allows mocking other tests, for instance of services, by providing a mock data repository backed by an array/iterator to the other service.

There are concrete implementations of WP\_Query and the WP Post Meta for `ISetReader`. Other interfaces, like `ISetStream` and `IStreamReader` are intended to wrap the data interface with external sources like CSV or JSON files.

### Services

[](#services)

**Namespace**: `Kanopi\Components\Services`

Interfaces to coordinate data processing from external sources into an local system resource.

### Transformers

[](#transformers)

**Namespace**: `Kanopi\Components\Transformers`

Components which consolidate and simplify the transformation of standard/scalar data types into coordinated structures of data for more readable and concise functionality. For instance, string utilities which sanitize or convert delimiters.

Code Quality
------------

[](#code-quality)

### PHPCS

[](#phpcs)

This project offers a PHPCS ruleset extended form rules made for Automattic's WordPress hosting services, including WPCS. A `Makefile` coordinates execution of these tests. Results of each test are piped into files labeled with the version in the format `phpcs-{version}.txt`.

Run all production level tests (PHP 8.0, 8.1, and 8.2):

```
make test
```

Run a specific language versions tests:

```
make {version}
```

where `{version}` is php80, php81, or php82

### PHPUnit

[](#phpunit)

PHPUnit is implemented to run a suite of test across some current and future components. A `Makefile`coordinates execution of these tests. Results of each test are piped into files labeled with the version in the format `phpunit-{version}.txt`.

Run all production level tests (PHP 8.0, 8.1, and 8.2):

```
make unit
```

Run a specific language versions tests:

```
make {version}
```

where `{version}` is unitphp80, unitphp81, or unitphp82

Quality Notes
-------------

[](#quality-notes)

Both tests suites can be run using the shell command `make`.

Testing without Make
--------------------

[](#testing-without-make)

If you are testing without Make available, you can run the tests directly with Composer installed with the target version of PHP.

### Composer PHPCS/PHPCBF

[](#composer-phpcsphpcbf)

```
composer -n phpcs -- --standard="{STANDARDS_FILE}" ./
composer -n phpcbf -- --standard="{STANDARDS_FILE}" ./
```

This runs using the version of PHP used by the CLI (outside of scope for these instructions)

Substitute the appropriate file name, from the project root directory for `{STANDARDS_FILE}`, for instance `--standard="./.phpcs-8.2.xml.dist"` for PHP 8.2.

### Composer PHPUnit

[](#composer-phpunit)

```
composer -n phpunit
```

This runs using the version of PHP used by the CLI (outside of scope for these instructions).

How To
------

[](#how-to)

### WordPress: Use the Base Post Type Entity Model

[](#wordpress-use-the-base-post-type-entity-model)

The `Kanopi\Components\Model\Data\WordPress\BasePostType` abstract class is a consolidated helper class for many common WordPress import situations. It will NOT support every use case, though is useful if your data follows the following requirements:

- Uses one or more scalar/simple meta fields
- Uses one or more **non-hierarchical** taxonomies
- Uses a cross-system Identifier which can be constructed/retrieved from any source/target repositories to match data for updates

Implementation can follow this pattern, for instance a Location of post type `location`. The model has the following fields:

PropertyTypeField NameAddressMeta Field`address`CityTaxonomy Term`city`Cross-system IdentifierMeta Field`id`Modified DateMeta Field`modifiedDate`Post TypePost Type`location`The model can be implemented using the following criteria:

- Add scalar types of type string to your class for `address` and `city`
- Extend the class and implement `extraInsertFieldMapping`, `metaFieldMapping`, and `taxonomyTermMapping`, which map the Meta and Taxonomy field names to the entity attributes. For instance, a Location with Address and City/Region: ```
    class Location extends BasePostType implements IIndexedEntity {
        /**
         * @var string
         */
        public string $address = '';

        /**
         * @var string
         */
        public string $city = '';

        /**
         * @var string
         */
        public string $id = '';

        /**
         * @var string
         */
        public string $modifiedDate = '';

        /**
         * {@inheritDoc}
         */
        function entityName(): string {
            return 'location';
        }

        /**
         * {@inheritDoc}
         */
        function uniqueIdentifier(): string {
            return $this->id;
        }

        /**
         * {@inheritDoc}
         */
        function version(): string {
            return $this->modifiedDate;
        }

        /**
         * {@inheritDoc}
         */
         function extraInsertFieldMapping(): array {
            return [];
         }

         /**
          * {@inheritDoc}
          */
         function metaFieldMapping(): array {
            return [
                'address' => $this->address,
                'id' => $this->id,
                'modifiedDate' => $this->modifiedDate,
            ];
         }

         /**
          * {@inheritDoc}
          */
         function taxonomyTermMapping(): array {
            return [
                'city' => $this->city,
            ];
         }
    }
    ```
- Now, when using a service, like `BasePostTypeWriter`, the built-in implementation of `systemTransform`returns an appropriate format for `wp_insert_post`

###  Health Score

32

—

LowBetter than 69% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity64

Established project with proven stability

 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

Every ~14 days

Total

37

Last Release

795d ago

PHP version history (2 changes)v1.0.0PHP &gt;=7.4

1.8.0PHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/bf9dca5c46910be861bb00920034637b5a36a1f6277413be6817a50a1ce6fc74?d=identicon)[kanopi\_studios](/maintainers/kanopi_studios)

---

Top Contributors

[![rleeson](https://avatars.githubusercontent.com/u/5117365?v=4)](https://github.com/rleeson "rleeson (46 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/kanopi-components/health.svg)

```
[![Health](https://phpackages.com/badges/kanopi-components/health.svg)](https://phpackages.com/packages/kanopi-components)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[pimcore/pimcore

Content &amp; Product Management Framework (CMS/PIM/E-Commerce)

3.8k3.8M508](/packages/pimcore-pimcore)[spatie/crawler

Crawl all internal links found on a website

2.8k18.5M67](/packages/spatie-crawler)[silverstripe/framework

The SilverStripe framework

7313.7M2.8k](/packages/silverstripe-framework)[blackfire/player

A powerful web crawler and web scraper with Blackfire support

49617.1k](/packages/blackfire-player)[drupal/drupal-extension

Drupal extension for Behat

22215.7M173](/packages/drupal-drupal-extension)

PHPackages © 2026

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