Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ real-world PHP projects.
- **Dot Notation Get/Set/Flatten**
- **Dynamic Config with Hooks**
- **Collection & Hooked Collection**
- **Unified Facade (`ArrayKit`)**
- **Traits for DTO & Hooking**
- **Pipeline for Collection Ops**
- **Global Helpers (`functions.php`)**
Expand Down Expand Up @@ -68,6 +69,11 @@ real-world PHP projects.
|-------------------|------------------------------------------------------------|
| **functions.php** | Global shortcut functions for frequent array/config tasks. |

### ➤ Facade

| Class | Description |
|-------------------|-----------------------------------------------------------------------------------------------|
| **ArrayKit** | Single entry point for arrays, dot tools, config, and collections (`single()`, `multi()`, etc.). |

## ✅ Requirements

Expand All @@ -82,6 +88,19 @@ composer require infocyph/arraykit

## 🚀 Quick Examples

### 🔹 One Facade Entry Point

```php
use Infocyph\ArrayKit\ArrayKit;

$isList = ArrayKit::single()->isList([1, 2, 3]); // true
$flat = ArrayKit::multi()->flatten([[1], [2, [3]]]); // [1, 2, 3]
$name = ArrayKit::dot()->get(['user' => ['n' => 'A']], 'user.n'); // A

$config = ArrayKit::config(['app' => ['env' => 'local']]);
$env = $config->get('app.env'); // local
```

### 🔹 Single-Dimensional Helpers

```php
Expand Down
11 changes: 11 additions & 0 deletions docs/array-helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ ArrayKit ships static helpers grouped by data shape:
- ``ArrayMulti`` for nested arrays / row collections
- ``BaseArrayHelper`` for lower-level shared operations

If you prefer one entry point, use ``Infocyph\ArrayKit\ArrayKit``:

.. code-block:: php

<?php
use Infocyph\ArrayKit\ArrayKit;

$isList = ArrayKit::single()->isList([1, 2, 3]);
$flat = ArrayKit::multi()->flatten([[1], [2, [3]]]);
$wrapped = ArrayKit::helper()->wrap('x');

Choosing the Right Helper
-------------------------

Expand Down
1 change: 1 addition & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Important behavior:

- ``loadArray()`` and ``loadFile()`` only load when config is currently empty.
- If already loaded, they return ``false`` and do not overwrite existing items.
- Facade-based config creation is documented in :doc:`facade`.

Reading Values
--------------
Expand Down
61 changes: 61 additions & 0 deletions docs/facade.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Facade
======

Use ``Infocyph\ArrayKit\ArrayKit`` as a single entry point for the package.

Classes:

- ``Infocyph\ArrayKit\ArrayKit``
- ``Infocyph\ArrayKit\Facade\ModuleProxy``

Why this exists
---------------

The facade keeps top-level usage consistent while preserving each module's native API.

Module Entry Points
-------------------

These methods return a lightweight ``ModuleProxy`` that forwards calls to static module methods.

.. code-block:: php

<?php
use Infocyph\ArrayKit\ArrayKit;

$isList = ArrayKit::single()->isList([1, 2, 3]);
$flat = ArrayKit::multi()->flatten([[1], [2, [3]]]);
$wrapped = ArrayKit::helper()->wrap('x');
$name = ArrayKit::dot()->get(['user' => ['name' => 'Alice']], 'user.name');

Factory Entry Points
--------------------

Use these when you want object instances instead of static helpers.

.. code-block:: php

<?php
use Infocyph\ArrayKit\ArrayKit;

$config = ArrayKit::config(['app' => ['env' => 'local']]);
$lazy = ArrayKit::lazyConfig(__DIR__.'/config');

$collection = ArrayKit::collection([1, 2, 3]);
$hooked = ArrayKit::hookedCollection(['name' => 'alice']);
$pipeline = ArrayKit::pipeline([1, 2, 3, 4]);

Behavior Notes
--------------

- ``single()``, ``multi()``, ``helper()``, and ``dot()`` return cached proxies.
- Proxy calls map directly to target static methods.
- Calling a missing method via proxy throws ``BadMethodCallException``.

Related Guides
--------------

- Array helpers: :doc:`array-helpers`
- Dot notation: :doc:`dot-notation`
- Collections: :doc:`collection`
- Configuration: :doc:`config`
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Contents

installation
quick-usage
facade
array-helpers
dot-notation
collection
Expand Down
15 changes: 15 additions & 0 deletions docs/quick-usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@ Quick Usage

This page shows copy-paste examples for common ArrayKit operations.

ArrayKit Facade Example
----------------------

.. code-block:: php

<?php
use Infocyph\ArrayKit\ArrayKit;

$isList = ArrayKit::single()->isList([1, 2, 3]);
$flat = ArrayKit::multi()->flatten([[1], [2, [3]]]);
$name = ArrayKit::dot()->get(['user' => ['name' => 'Alice']], 'user.name');

$config = ArrayKit::config(['app' => ['env' => 'local']]);
$env = $config->get('app.env');

ArraySingle Example
-------------------

Expand Down
25 changes: 25 additions & 0 deletions docs/rule-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Object-style data pipeline and fluent transformations:
Configuration storage with optional get/set hooks:
:doc:`config`

Single facade entrypoint for modules and factories:
:doc:`facade`

DTO and hook traits plus global helper functions:
:doc:`traits-and-helpers`

Expand Down Expand Up @@ -95,6 +98,28 @@ Global Helper Functions
function collect(mixed $data = []): Collection
function chain(mixed $data): Pipeline

ArrayKit Facade
---------------

.. code-block:: php

public static function single(): ModuleProxy
public static function multi(): ModuleProxy
public static function helper(): ModuleProxy
public static function dot(): ModuleProxy
public static function config(array $items = []): Config
public static function lazyConfig(string $directory, string $extension = 'php', array $items = []): LazyFileConfig
public static function collection(mixed $data = []): Collection
public static function hookedCollection(mixed $data = []): HookedCollection
public static function pipeline(mixed $data): Pipeline

Facade ModuleProxy
------------------

.. code-block:: php

public function __call(string $method, array $arguments): mixed

BaseArrayHelper
---------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion src/Array/BaseArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public static function tap(array $array, callable $callback): array
* filled with the numbers 1 through $number.
*
* Example:
* ArrayKit::times(3, function ($i) {
* ArrayKit::helper()->times(3, function ($i) {
* return "Row #{$i}";
* });
* // Output: ["Row #1", "Row #2", "Row #3"]
Expand Down
93 changes: 93 additions & 0 deletions src/ArrayKit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace Infocyph\ArrayKit;

use Infocyph\ArrayKit\Array\ArrayMulti;
use Infocyph\ArrayKit\Array\ArraySingle;
use Infocyph\ArrayKit\Array\BaseArrayHelper;
use Infocyph\ArrayKit\Array\DotNotation;
use Infocyph\ArrayKit\Collection\Collection;
use Infocyph\ArrayKit\Collection\HookedCollection;
use Infocyph\ArrayKit\Collection\Pipeline;
use Infocyph\ArrayKit\Config\Config;
use Infocyph\ArrayKit\Config\LazyFileConfig;
use Infocyph\ArrayKit\Facade\ModuleProxy;

/**
* Unified static facade for the package.
*
* Usage:
* - ArrayKit::single()->isList(...)
* - ArrayKit::multi()->flatten(...)
* - ArrayKit::helper()->times(...)
* - ArrayKit::dot()->get(...)
*/
final class ArrayKit
{
/**
* @var array<class-string, ModuleProxy>
*/
private static array $moduleProxies = [];

private function __construct() {}

public static function collection(mixed $data = []): Collection
{
return Collection::make($data);
}

public static function config(array $items = []): Config
{
$config = new Config();
if ($items !== []) {
$config->loadArray($items);
}

return $config;
}

public static function dot(): ModuleProxy
{
return self::proxy(DotNotation::class);
}

public static function helper(): ModuleProxy
{
return self::proxy(BaseArrayHelper::class);
}

public static function hookedCollection(mixed $data = []): HookedCollection
{
return HookedCollection::make($data);
}

public static function lazyConfig(string $directory, string $extension = 'php', array $items = []): LazyFileConfig
{
return new LazyFileConfig($directory, $extension, $items);
}

public static function multi(): ModuleProxy
{
return self::proxy(ArrayMulti::class);
}

public static function pipeline(mixed $data): Pipeline
{
return Collection::make($data)->process();
}

public static function single(): ModuleProxy
{
return self::proxy(ArraySingle::class);
}

/**
* @param class-string $className
*/
private static function proxy(string $className): ModuleProxy
{
return self::$moduleProxies[$className] ?? self::$moduleProxies[$className] = new ModuleProxy($className);
}
}
26 changes: 26 additions & 0 deletions src/Facade/ModuleProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Infocyph\ArrayKit\Facade;

use BadMethodCallException;

final readonly class ModuleProxy
{
/**
* @param class-string $targetClass
*/
public function __construct(
private string $targetClass,
) {}

public function __call(string $method, array $arguments): mixed
{
if (!method_exists($this->targetClass, $method)) {
throw new BadMethodCallException("Method {$this->targetClass}::{$method} does not exist.");
}

return $this->targetClass::$method(...$arguments);
}
}
Loading
Loading