PHPackages                             spinitron/precis - 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. [Localization &amp; i18n](/categories/localization)
4. /
5. spinitron/precis

ActiveLibrary[Localization &amp; i18n](/categories/localization)

spinitron/precis
================

Implements PRECIS Framework, IDNA Bidi Rule, Unicode Bidi properties

0.3.2(8y ago)61.4k↓100%ISCPHPPHP &gt;=5.4.0

Since Sep 19Pushed 8y ago3 watchersCompare

[ Source](https://github.com/tom--/precis)[ Packagist](https://packagist.org/packages/spinitron/precis)[ RSS](/packages/spinitron-precis/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (4)Used By (0)

International username, password, and nickname handling with PRECIS Framework
=============================================================================

[](#international-username-password-and-nickname-handling-with-precis-framework)

### Summary

[](#summary)

[PRECIS](https://tools.ietf.org/html/rfc8264), "Preparation, Enforcement, and Comparison of Internationalized Strings", is a framework for handling Unicode strings representing things like network addresses, [identifiers and passwords](https://tools.ietf.org/html/rfc8265), and [nicknames](https://tools.ietf.org/html/rfc8266).

In PRECIS terms, a client (e.g. web browser) **prepares** a string (e.g. username, password) before sending it over the network. A server (e.g. a PHP web app) **enforces** specific rules (e.g. checking for disallowed characters, case mapping, etc.) on the string *before* accepting and using it. Enforcement involves an accept/reject decision and may involve changing the string using a PRECIS profile-specific kind of normalization. When comparing two strings, both are enforced before comparion. If a hash function is used in the comparison (e.g. for a password), enforcement comes before hashing and comparison.

The PRECIS RFCs standardize such preparation and enforcement (obsoleting older standards) and this package provides a PHP implementation.

### Functionality

[](#functionality)

The `Precis` class provides static methods to:

- test strings against the strings classes defined in [PRECIS Framework RFC 8264](https://tools.ietf.org/html/rfc8264)

    - IdentifierClass
    - FreeformClass
- prepare and enforce strings according to the profiles

    - UsernameCaseMapped [RFC 8265 Section 3.3](https://tools.ietf.org/html/rfc8265#section-3.3)
    - UsernameCasePreserved [RFC 8265 Section 3.4](https://tools.ietf.org/html/rfc8265#section-3.4)
    - OpaqueString (used for passwords etc.) [RFC 8265 Section 4.2](http://tools.ietf.org/html/rfc7613#section-4.2)
    - Nickname [RFC 8266](https://tools.ietf.org/html/rfc8266)

In order to implement these, certain Unicode functionality is required that was absent in PHP before PHP 7.0 introduced [IntlChar](http://php.net/manual/en/class.intlchar.php). The package has another class as a stop-gap.

- `Bidi` provides static methods for:

    - Getting the Unicode [Bidi](http://unicode.org/faq/bidi.html) [property](http://www.unicode.org/reports/tr9/) for a character
    - Applying the [IDNA Bidi Rule](https://tools.ietf.org/html/rfc5893)

(Note: The `CaseFold` class in v0.1.1 of this package was removed after PRECIS removed it in revised RFCs.)

### Methods

[](#methods)

All public methods are static.

```
// test for PRECIS string classes
public static function isIdentifier(string $string): bool
public static function isFreeform(string $string): bool

// prepare for PRECIS profiles
public static function prepareUsernameCaseMapped(string $string): string|bool
public static function prepareUsernameCasePreserved(string $string): string|bool
public static function prepareOpaqueString(string $string): string|bool
public static function prepareNickname(string $string): string|bool

// enforce PRECIS profiles
public static function enforceUsernameCaseMapped(string $string): string|bool
public static function enforceUsernameCasePreserved(string $string): string|bool
public static function enforceOpaqueString(string $string): string|bool
public static function enforceNickname(string $string): string|bool
```

This package also has some general Unicode utilities that were required before PHP 7 introduced the `IntlChar` class. These remain as we maintain PHP 5.4 compat for now. And we contunue to use mbstring for the Unicode `toLowerCase()` operation.

```
// general UTF-8 character utilities
public static function utf8chr(int $ord): string|null
public static function utf8ord(string $string, int $pos = 0): int
public static function codePoint2utf8(string $codePoint): string|null|false
public static function utf82CodePoint(string $string, int $pos = 0, string $style = 'U+'): string

// Unicode Bidi class and IDNA Bidi rule
Bidi::getClass(string $char): string
public static function rule(string $string): bool
```

### Data

[](#data)

The `Bidi` class has its own "data trait" that contains the relevant data from the Unicode Character Database. They are PHP classes in order to exploit opcode caches. They are traits not because I plan to reuse them elsewhere but for convenience. First, because they are automatically generated from the UCD and, second, because it's easier to work on the corresponding methods without the big array literals in the same editor.

The generators for the data traits are in the `data` directory. They download the relevant UCD files and write the PHP trait classes to standard output. So you can regenerate them, for example, as follows (assuming php is in your path):

```
cd path/to/precis/project/dir
php data/generateBidi.php > BidiDataTrait.php
php data/generateCaseFold.php > CaseFoldDataTrait.php

```

### Unit tests

[](#unit-tests)

The `Precis` tests are incomplete because I could not find test vectors for PRECIS string classes or profiles or for the Bidi Rule.

The following are relatively well tested:

- UTF-8 utility functions are tested on every Unicode code point
- `Bidi::getClass()`. NOTE: this test downloads UnicideData.txt from UCD (1.5 MB)
- The CONTEXTO and CONTEXTJ rules
- `Precis::getPrecisProperty()`

The `DerivedPropertyValueTest` uses the table of derived property values from [IANA](https://www.iana.org/assignments/precis-tables-6.3.0/precis-tables-6.3.0.xhtml) that's [stuck on Unicode 6.3.0](https://tools.ietf.org/html/rfc8264#section-11.1). Hence we ignore tests where the IANA table says UNASSIGNED and Precis says something else.

### Copyright and license

[](#copyright-and-license)

- Copyright (c) 2015-2018 Spinitron LLC
- ISC license

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity21

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.8% 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 ~441 days

Total

3

Last Release

3012d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c8c8a3ea969dee0a429efdc385ea9585bdd20fa33e7cd0d689e1f224631a4313?d=identicon)[spinitron](/maintainers/spinitron)

---

Top Contributors

[![tom--](https://avatars.githubusercontent.com/u/1178722?v=4)](https://github.com/tom-- "tom-- (23 commits)")[![pcrov](https://avatars.githubusercontent.com/u/8586747?v=4)](https://github.com/pcrov "pcrov (1 commits)")

---

Tags

i18nunicodepasswordidnusernamenicknamebidiprecis

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/spinitron-precis/health.svg)

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

###  Alternatives

[symfony/string

Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way

1.8k724.1M827](/packages/symfony-string)[symfony/intl

Provides access to the localization data of the ICU library

2.6k199.8M1.1k](/packages/symfony-intl)[gettext/gettext

PHP gettext manager

70130.2M102](/packages/gettext-gettext)[gettext/languages

gettext languages with plural rules

7530.3M11](/packages/gettext-languages)[punic/punic

PHP-Unicode CLDR

1542.9M29](/packages/punic-punic)[inpsyde/multilingual-press

Simply THE multisite-based free open source plugin for your multilingual websites.

2414.0k1](/packages/inpsyde-multilingual-press)

PHPackages © 2026

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