PHP Classes

How to Use a XOOPS PHP Library to Quickly Perform Actions to Access Several Types of Data using the Package XOOPS helpers: Helper class functions to use with XOOPS

Recommend this page to a friend!
  Info   Documentation   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Last Updated Ratings Unique User Downloads Download Rankings
2026-04-13 (3 days ago) RSS 2.0 feedNot yet rated by the usersTotal: Not yet counted Not yet ranked
Version License PHP version Categories
xoops_helpers 1.0GNU General Publi...8.2Libraries, PHP 8
Description 

Author

This class provides helper class functions to use with XOOPS.

It provides a set of classes useful to use in Web application development using XOOPS.

Currently it provides classes to the following:

- Generate HTML tags from parameter values

- Generate URLs for XOOPS modules, assets and themes

- Retrieve paths for XOOPS language files, modules, cache or uploaded files

- Get XOOPS configuration values

- Cache the results of callback functions

- Access array values using the dot notation

- Format number values of quantities, file sizes, money amounts, and order numbers

- Manipulate collections of values

Picture of Michael Beck
Name: Michael Beck <contact>
Classes: 7 packages by
Country: United States United States
Innovation award
Innovation award
Nominee: 4x

Winner: 1x

Instructions

What Is This?

XOOPS Helpers is a standalone utility library that makes every XOOPS module safer and shorter by replacing the repetitive, error-prone boilerplate every module developer writes over and over:

This package has 41 source files. 151 tests. Zero configuration. XSS-safe HTML by default. One composer require.

Before — scattered across every XOOPS module

$escaped  = htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$url      = XOOPS_URL . '/modules/' . $dirname . '/article.php?id=' . $id;
$path     = XOOPS_ROOT_PATH . '/modules/' . $dirname . '/language/' . $language . '/blocks.php';
$sitename = $GLOBALS['xoopsConfig']['sitename'];

After

$escaped  = HtmlBuilder::escape($value);
$url      = Url::module($dirname, 'article.php', ['id' => $id]);
$path     = Path::module($dirname, "language/{$language}/blocks.php");
$sitename = Config::get('system.sitename');

That first line is not just shorter — it is structurally safer. Every manual htmlspecialchars() call is a place where a future developer can introduce a stored XSS vulnerability by forgetting it once.

HtmlBuilder escapes all attribute values and class names automatically — the source of the vast majority of real-world XSS.

Tag content is your responsibility, intentionally: content can legitimately contain HTML (rendered markup, trusted template fragments).

The safe path is explicit: pass user-supplied content through HtmlBuilder::escape().

This htmlspecialchars pattern appears 30+ times in the XOOPS Core alone — each one a place where this library makes the correct choice the easiest choice.

Documentation

XOOPS Helpers

Convention-over-configuration utility and service helpers for XOOPS CMS development.

License: GPL v2 PHP 8.2+

41 source files. 151 tests. Zero configuration. XSS-safe HTML by default. One composer require.

What Is This?

XOOPS Helpers is a standalone utility library that makes every XOOPS module safer and shorter by replacing the repetitive, error-prone boilerplate every module developer writes over and over:

// Before ? scattered across every XOOPS module
$escaped  = htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$url      = XOOPS_URL . '/modules/' . $dirname . '/article.php?id=' . $id;
$path     = XOOPS_ROOT_PATH . '/modules/' . $dirname . '/language/' . $language . '/blocks.php';
$sitename = $GLOBALS['xoopsConfig']['sitename'];

// After
$escaped  = HtmlBuilder::escape($value);
$url      = Url::module($dirname, 'article.php', ['id' => $id]);
$path     = Path::module($dirname, "language/{$language}/blocks.php");
$sitename = Config::get('system.sitename');

> That first line is not just shorter ? it is structurally safer. > Every manual htmlspecialchars() call is a place where a future developer can introduce > a stored XSS vulnerability by forgetting it once. HtmlBuilder escapes all attribute > values and class names automatically ? the source of the vast majority of real-world XSS. > Tag content is your responsibility, intentionally: content can legitimately contain HTML > (rendered markup, trusted template fragments). The safe path is explicit: pass user-supplied > content through HtmlBuilder::escape(). This htmlspecialchars pattern appears 30+ times > in the XOOPS Core alone ? each one a place where this library makes the correct choice the > easiest choice.

Requirements

  • PHP 8.2 or later with the `ext-mbstring` extension
  • No other runtime dependencies

Optional extensions for enhanced functionality: - ext-intl ? locale-aware number and date formatting - ext-apcu ? APCu caching backend - ext-zip ? zip/unzip filesystem operations

Installation

composer require xoops/helpers

Quick Start

use Xoops\Helpers\Utility\HtmlBuilder;
use Xoops\Helpers\Service\Url;
use Xoops\Helpers\Service\Path;
use Xoops\Helpers\Service\Config;
use Xoops\Helpers\Service\Cache;
use Xoops\Helpers\Utility\Arr;
use Xoops\Helpers\Utility\Str;
use Xoops\Helpers\Utility\Number;
use Xoops\Helpers\Utility\Collection;

// HTML ? attribute values escaped automatically; use text() for tag content
HtmlBuilder::attributes(['class' => 'btn', 'disabled' => true, 'data-id' => $userInput]);
HtmlBuilder::classes(['btn', 'btn-primary' => $isPrimary, 'disabled' => false]);
HtmlBuilder::tag('div', ['class' => 'alert'], HtmlBuilder::text($userMessage)); // user text
HtmlBuilder::tag('div', ['class' => 'body'], $renderedHtmlBlock);               // trusted HTML

// URLs ? zero concatenation
Url::module('news', 'article.php', ['id' => 42]);
Url::asset('themes/starter/css/style.css');
Url::theme('starter', 'images/logo.png');

// Paths ? cross-platform, always correct; languageFile() resolves language fallback
Path::module('news', 'language/english/main.php');
Path::languageFile('news', $language, 'main.php'); // tries $language, falls back to english
Path::storage('caches/xmf');
Path::uploads('images/avatars');

// Config ? dot notation, auto-cached
Config::get('system.sitename', 'XOOPS');
Config::get('news.items_per_page', 10);

// Cache ? compute-and-cache in one call
$articles = Cache::remember('news_latest', 3600, fn() => loadArticles());

// Arrays ? dot notation, pluck, group, filter
$value   = Arr::get($config, 'database.host', 'localhost');
$names   = Arr::pluck($users, 'uname', 'uid');
$grouped = Arr::groupBy($articles, 'category_id');

// Strings ? slug, validation, case conversion
Str::slug('Hello World');        // "hello-world"
Str::isEmail('a@example.com');   // true
Str::camel('module_config');     // "moduleConfig"
Str::limit($body, 150);          // "First 150 chars..."
Str::random(32);                 // cryptographically secure

// Numbers ? human-readable formatting
Number::fileSize(1572864);       // "1.50 MB"
Number::forHumans(2300000);      // "2.3M"
Number::ordinal(21);             // "21st"
Number::currency(99.99, 'EUR', 'de_DE');

// Collections ? fluent data transformation
Collection::make($items)
    ->filter(fn($item) => $item['active'])
    ->sortBy('name')
    ->pluck('title', 'id')
    ->all();

Library Contents

Tier 0 ? Utility (Pure PHP, zero XOOPS dependency)

These work anywhere ? CLI scripts, cron jobs, unit tests ? no XOOPS boot required.

| Class | Purpose | |-------|---------| | HtmlBuilder | XSS-safe HTML: attributes, classes, tag, escape, text, stylesheet, script, meta ? attribute values escaped automatically; use text() to explicitly escape tag content | | Arr | Array helpers with dot notation: get, set, has, pluck, groupBy, sortBy, where, flatten, dot/undot, only/except, first/last, wrap, collapse | | Str | String helpers: slug, camel/snake/studly/kebab, limit, random, contains/startsWith/endsWith, between, mask, isEmail/isUrl/isIp/isJson/isHexColor | | Number | Number formatting: format, fileSize, forHumans, percentage, ordinal, currency, clamp | | Date | Date helpers with injectable time source: now, range, diff, isValid, addDays/subDays, isWeekend/isToday/isPast/isFuture, reformat, age | | Value | Value resolution: value (Closure resolver), blank/filled, optional (null-safe access), once (memoization), missing (sentinel) | | Collection | Fluent array wrapper: map, filter, reject, reduce, pluck, groupBy, sortBy, first/last, chunk, take/skip, sum/avg/min/max, when, pipe, tap | | Pipeline | Data transformation chains: Pipeline::send($v)->pipe(fn)->pipe(fn)->thenReturn() | | Stringable | Fluent string builder: Stringable::of($s)->trim()->lower()->slug()->toString() | | Filesystem | File operations: readJson/putJson, mimeType, isImage, mkdir, deleteDirectory, copyDirectory, zip/unzip, readChunked | | Environment | Runtime detection: isProduction/isDevelopment/isTesting, get/require/has | | Benchmark | Profiling: measure (time + memory), time, average (multi-iteration) | | Encoding | URL-safe base64: base64UrlEncode/base64UrlDecode | | Data | Conversion: toArray, toObject, toQueryString, fromQueryString | | Retry | Error recovery: retry (with backoff), rescue (with fallback) | | ThrowHelper | Guard clauses: throwIf, throwUnless | | Transform | Conditional transforms: transform (if filled), when (predicate-based) | | Tap | Side-effect helper: call callback, return original value |

Tier 1 ? Contracts (Interfaces)

| Interface | Purpose | |-----------|---------| | PathLocatorInterface | Filesystem path resolution | | UrlGeneratorInterface | URL generation | | CacheInterface | Cache operations | | ConfigProviderInterface | Configuration loading | | DateTimeProviderInterface | Clock abstraction for testing |

Tier 2 ? Service Facades (Zero-config, XOOPS-aware)

| Facade | Purpose | Override | |--------|---------|----------| | Path | Path::base(), module(), storage(), uploads(), themes(), languageFile() | Path::use($locator) | | Url | Url::to(), asset(), module(), theme() | Url::use($generator) | | Config | Config::get(), set(), has(), all(), registerLoader() | Config::setProvider($p) | | Cache | Cache::get(), set(), forget(), remember(), flush() | Cache::use($adapter) |

All facades work immediately using XOOPS constants (XOOPS_ROOT_PATH, XOOPS_URL, etc.). Override with ::use() for testing or custom installations. Reset with ::reset().

Tier 3 ? Providers (Default implementations)

| Provider | Purpose | |----------|---------| | DefaultPathLocator | Maps to XOOPS constants | | DefaultUrlGenerator | Uses XOOPS_URL, falls back to $_SERVER | | XoopsCacheAdapter | Auto-detects: XoopsCache, APCu, or file cache | | ArrayCache | In-memory cache for testing | | SystemDateTimeProvider | System clock |

Tier 4 ? Integration (XOOPS-specific)

| Component | Purpose | |-----------|---------| | XoopsCollection | XoopsCollection::fromHandler($handler, $criteria) with pluckVar() for getVar() | | AssetUrlPlugin | Smarty: <{asset_url path="css/style.css"}> | | FormatNumberPlugin | Smarty: <{format_number value=$size type="filesize"}> | | CssClassesPlugin | Smarty: <{css_classes classes=$classArray}> | | PluginRegistrar | Register all Smarty plugins at once |

Cross-cutting

| Component | Purpose | |-----------|---------| | Tappable | Trait adding tap() to any class | | functions.php | Optional global function wrappers (not auto-loaded) |

Architecture

Dependencies flow downward only. Tier 0 classes can be used in any PHP 8.2+ project without XOOPS ? in CLI scripts, cron jobs, and unit tests with no bootstrap required.

graph TD
    T4["Tier 4 · Integration
    Depend on XOOPS classes
    XoopsObject · Smarty"]

    T3["Tier 3 · Provider
    Default implementations
    XOOPS-aware"]

    T2["Tier 2 · Service
    Static facades
    Depend on XOOPS constants"]

    T1["Tier 1 · Contracts
    Interfaces only
    No implementation"]

    T0["Tier 0 · Utility
    Pure PHP · Zero dependencies
    Works anywhere"]

    T4 --> T3
    T3 --> T2
    T2 --> T1
    T1 --> T0

    style T4 fill:#b7e0ff,stroke:#4a90d9,color:#000
    style T3 fill:#c8f0d0,stroke:#3a9a5c,color:#000
    style T2 fill:#fff3b0,stroke:#c8a200,color:#000
    style T1 fill:#ffd6a5,stroke:#d48000,color:#000
    style T0 fill:#ffadad,stroke:#c0392b,color:#000

Optional Global Functions

The file src/functions.php provides short function wrappers like collect(), str(), pipeline(), tap(), retry(), env(), etc. It is not auto-loaded ? opt in explicitly.

Recommended pattern: load it once in your XOOPS bootstrap, not in individual module files. This prevents redundant require calls across a multi-module installation:

// In mainfile.php or a central preload script ? once per request
if (file_exists(XOOPS_ROOT_PATH . '/vendor/xoops/helpers/src/functions.php')) {
    require_once XOOPS_ROOT_PATH . '/vendor/xoops/helpers/src/functions.php';
}

If you are building a single module and do not control the bootstrap, load it in your module's entry point:

require_once 'vendor/xoops/helpers/src/functions.php';

$slug = str('Hello World')->slug()->toString();
$data = collect($items)->filter(fn($i) => $i['active'])->pluck('name')->all();
$value = retry(3, fn() => fetchFromApi(), sleepMs: 500);

All functions are guarded with function_exists() to prevent fatal redeclaration errors.

Compatibility

XOOPS 2.5.x

Fully compatible. Designed for inclusion in XOOPS 2.5.12+.

XMF 1.x (xoops/xmf)

No conflicts. Different namespace (Xoops\Helpers\ vs Xmf\), no shared class names, no shared global functions. Both can be loaded simultaneously via Composer.

Where both libraries offer related functionality, they serve different scopes:

| Area | XMF 1.x | XOOPS Helpers | |------|---------|---------------| | URL/Path | $helper->url() ? module-scoped | Url::module() ? global, works without module context | | Config | $helper->getConfig() ? per-module handler | Config::get('mod.key') ? dot notation, cached | | Cache | Helper\Cache::cacheRead() ? module-prefixed | Cache::remember() ? global, auto-backend | | Random | Random::generateKey() ? SHA512 hash tokens | Str::random() ? URL-safe strings, configurable length | | SEO | Metagen::generateSeoTitle() ? full meta tags | Str::slug() ? pure string transformation |

Migration Strategy

You do not need to refactor existing XMF 1.x code to adopt this library. Both coexist safely. The recommended approach depends on where you are in a project:

Starting a new module ? use XOOPS Helpers exclusively from the first line. There is no legacy to consider and you get the full benefit of automatic escaping, dot-notation config, and fluent collections from day one.

Actively developing an existing module ? use XOOPS Helpers for all new code and any functions you touch during the current sprint. When you open a file to add a feature, convert the XMF 1.x patterns in that file as you go. Do not schedule a dedicated refactoring sprint; let the migration happen organically as the module evolves.

Maintaining a stable module with no active development ? do nothing. The libraries coexist with zero conflicts. The migration cost is not justified by a pure maintenance ticket. If it is not broken, leave it until you have a reason to open the file.

When you do migrate a specific pattern, the Cache facade is the most common conversion:

// XMF 1.x ? before
if (!$data = \XoopsCache::read("{$dirname}_config")) {
    $data = xoops_getModuleConfig($dirname);
    \XoopsCache::write("{$dirname}_config", $data);
}

// XOOPS Helpers ? after
$data = Cache::remember("{$dirname}_config", 3600, fn() => xoops_getModuleConfig($dirname));

XMF 2.0 (xoops/xmf next generation)

Designed as a companion. XMF 2.0 provides the architectural framework (Repository, EventBus, Container, QueryBuilder); XOOPS Helpers provides the day-to-day utilities (Arr, Str, Number, HtmlBuilder, Collection). XMF 2.0 will declare xoops/helpers as a dependency ? requiring XMF 2.0 pulls this library in automatically.

Testing

composer install
vendor/bin/phpunit

All services are mockable for testing:

use Xoops\Helpers\Service\{Path, Url, Config, Cache};
use Xoops\Helpers\Provider\ArrayCache;

// Inject test implementations
Cache::use(new ArrayCache());
Config::registerLoader('mymod', fn() => ['key' => 'value']);

// Reset after tests
Cache::reset();
Config::reset();
Path::reset();
Url::reset();

The Date utility accepts an injectable time provider:

use Xoops\Helpers\Utility\Date;
use Xoops\Helpers\Contracts\DateTimeProviderInterface;

Date::setProvider(new class implements DateTimeProviderInterface {
    public function now(): \DateTimeImmutable {
        return new \DateTimeImmutable('2025-06-15 12:00:00');
    }
});

Date::isToday('2025-06-15'); // true ? deterministic in tests
Date::resetProvider();

Contributing

Contributions are welcome. Please follow XOOPS coding standards: - declare(strict_types=1) in every file - PHP 8.2+ features (readonly, match, named arguments, union types) - Final classes for utility classes - Full type hints on all methods - PHPUnit tests for all new functionality

Documentation

See TUTORIAL.md for a comprehensive guide with before/after comparisons from real XOOPS Core and module code.

License

GNU GPL v2 or later. See LICENSE for details.


  Files folder image Files (90)  
File Role Description
Files folder image.github (2 files, 2 directories)
Files folder imagedocs (1 file)
Files folder imagesrc (1 file, 6 directories)
Files folder imagestubs (1 file)
Files folder imagetests (1 file, 1 directory)
Accessible without login Plain text file .coderabbit.yaml Data Auxiliary data
Accessible without login Plain text file .editorconfig Data Auxiliary data
Accessible without login Plain text file .scrutinizer.yml Data Auxiliary data
Accessible without login Plain text file CHANGELOG.md Data Auxiliary data
Accessible without login Plain text file CODEOWNERS Data Auxiliary data
Accessible without login Plain text file composer.json Data Auxiliary data
Accessible without login Plain text file CONTRIBUTING.md Data Auxiliary data
Accessible without login Plain text file LICENSE Lic. License text
Accessible without login Plain text file phpstan.neon Data Auxiliary data
Accessible without login Plain text file phpunit.xml Data Auxiliary data
Accessible without login Plain text file README.md Doc. Documentation
Accessible without login Plain text file SECURITY.md Data Auxiliary data
Accessible without login Plain text file SUPPORT.md Data Auxiliary data

  Files folder image Files (90)  /  .github  
File Role Description
Files folder imageISSUE_TEMPLATE (3 files)
Files folder imageworkflows (4 files)
  Accessible without login Plain text file dependabot.yml Data Auxiliary data
  Accessible without login Plain text file PULL_REQUEST_TEMPLATE.md Data Auxiliary data

  Files folder image Files (90)  /  .github  /  ISSUE_TEMPLATE  
File Role Description
  Accessible without login Plain text file bug_report.yml Data Auxiliary data
  Accessible without login Plain text file config.yml Data Auxiliary data
  Accessible without login Plain text file feature_request.yml Data Auxiliary data

  Files folder image Files (90)  /  .github  /  workflows  
File Role Description
  Accessible without login Plain text file ci.yml Data Auxiliary data
  Accessible without login Plain text file code-coverage.yml Data Auxiliary data
  Accessible without login Plain text file codeql.yml Data Auxiliary data
  Accessible without login Plain text file dependency-review.yml Data Auxiliary data

  Files folder image Files (90)  /  docs  
File Role Description
  Accessible without login Plain text file TUTORIAL.md Data Auxiliary data

  Files folder image Files (90)  /  src  
File Role Description
Files folder imageContracts (5 files)
Files folder imageIntegration (1 file, 1 directory)
Files folder imageProvider (5 files)
Files folder imageService (4 files)
Files folder imageTraits (1 file)
Files folder imageUtility (20 files)
  Accessible without login Plain text file functions.php Aux. Auxiliary script

  Files folder image Files (90)  /  src  /  Contracts  
File Role Description
  Plain text file CacheInterface.php Class Class source
  Plain text file ConfigProviderInterface.php Class Class source
  Plain text file DateTimeProviderInterface.php Class Class source
  Plain text file PathLocatorInterface.php Class Class source
  Plain text file UrlGeneratorInterface.php Class Class source

  Files folder image Files (90)  /  src  /  Integration  
File Role Description
Files folder imageSmarty (4 files)
  Plain text file XoopsCollection.php Class Class source

  Files folder image Files (90)  /  src  /  Integration  /  Smarty  
File Role Description
  Plain text file AssetUrlPlugin.php Class Class source
  Plain text file CssClassesPlugin.php Class Class source
  Plain text file FormatNumberPlugin.php Class Class source
  Plain text file PluginRegistrar.php Class Class source

  Files folder image Files (90)  /  src  /  Provider  
File Role Description
  Plain text file ArrayCache.php Class Class source
  Plain text file DefaultPathLocator.php Class Class source
  Plain text file DefaultUrlGenerator.php Class Class source
  Plain text file SystemDateTimeProvider.php Class Class source
  Plain text file XoopsCacheAdapter.php Class Class source

  Files folder image Files (90)  /  src  /  Service  
File Role Description
  Plain text file Cache.php Class Class source
  Plain text file Config.php Class Class source
  Plain text file Path.php Class Class source
  Plain text file Url.php Class Class source

  Files folder image Files (90)  /  src  /  Traits  
File Role Description
  Plain text file Tappable.php Class Class source

  Files folder image Files (90)  /  src  /  Utility  
File Role Description
  Plain text file Arr.php Class Class source
  Plain text file Benchmark.php Class Class source
  Plain text file Collection.php Class Class source
  Plain text file Data.php Class Class source
  Plain text file Date.php Class Class source
  Plain text file Encoding.php Class Class source
  Plain text file Environment.php Class Class source
  Plain text file Filesystem.php Class Class source
  Plain text file HtmlBuilder.php Class Class source
  Plain text file MissingValue.php Class Class source
  Plain text file Number.php Class Class source
  Plain text file Optional.php Class Class source
  Plain text file Pipeline.php Class Class source
  Plain text file Retry.php Class Class source
  Plain text file Str.php Class Class source
  Plain text file Stringable.php Class Class source
  Plain text file Tap.php Class Class source
  Plain text file ThrowHelper.php Class Class source
  Plain text file Transform.php Class Class source
  Plain text file Value.php Class Class source

  Files folder image Files (90)  /  stubs  
File Role Description
  Plain text file xoops-stubs.php Class Class source

  Files folder image Files (90)  /  tests  
File Role Description
Files folder imageUnit (3 directories)
  Accessible without login Plain text file bootstrap.php Aux. Configuration script

  Files folder image Files (90)  /  tests  /  Unit  
File Role Description
Files folder imageIntegration (1 file, 1 directory)
Files folder imageService (4 files)
Files folder imageUtility (16 files)

  Files folder image Files (90)  /  tests  /  Unit  /  Integration  
File Role Description
Files folder imageSmarty (3 files)
  Plain text file XoopsCollectionTest.php Class Class source

  Files folder image Files (90)  /  tests  /  Unit  /  Integration  /  Smarty  
File Role Description
  Plain text file AssetUrlPluginTest.php Class Class source
  Plain text file CssClassesPluginTest.php Class Class source
  Plain text file FormatNumberPluginTest.php Class Class source

  Files folder image Files (90)  /  tests  /  Unit  /  Service  
File Role Description
  Plain text file CacheTest.php Class Class source
  Plain text file ConfigTest.php Class Class source
  Plain text file PathTest.php Class Class source
  Plain text file UrlTest.php Class Class source

  Files folder image Files (90)  /  tests  /  Unit  /  Utility  
File Role Description
  Plain text file ArrTest.php Class Class source
  Plain text file CollectionTest.php Class Class source
  Plain text file DateTest.php Class Class source
  Plain text file EncodingTest.php Class Class source
  Plain text file EnvironmentTest.php Class Class source
  Plain text file FilesystemTest.php Class Class source
  Plain text file HtmlBuilderTest.php Class Class source
  Plain text file NumberTest.php Class Class source
  Plain text file PipelineTest.php Class Class source
  Plain text file RetryTest.php Class Class source
  Plain text file StringableTest.php Class Class source
  Plain text file StrTest.php Class Class source
  Plain text file TapTest.php Class Class source
  Plain text file ThrowHelperTest.php Class Class source
  Plain text file TransformTest.php Class Class source
  Plain text file ValueTest.php Class Class source

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads  
 100%
Total:0
This week:0