scriptmancer/support

Collection of useful classes and functions

v0.9.5 2025-05-08 10:26 UTC

This package is auto-updated.

Last update: 2025-05-09 11:44:43 UTC


README

Support package for the Nazim framework.

Features

  • Debug helpers using Kint
  • Collection implementation similar to Tighten Collect
  • Immutable Date and DateObject helpers
  • Fluent string manipulation with Stringable
  • Comprehensive array manipulation utilities
  • String helper functions
  • Locale-specific string sorting with Collator integration
  • Locale-aware number formatting with NumberFormatter
  • Advanced collection debugging with CollectionDebugger
  • Secure password hashing and cryptography with Hash
  • OpenSSL encryption/decryption utilities
  • Pipeline pattern for chaining operations

Installation

composer require scriptmancer/support

Usage

Debug Helpers

This package provides debugging functionality powered by Kint:

// Dump a variable and continue execution
d($var);

// Dump a variable and die
dd($var);

Collections

Work with arrays in an object-oriented way using the rich Collection class:

// Create a collection
$collection = collect([1, 2, 3, 4, 5]);

// Basic operations
$count = $collection->count(); // 5
$first = $collection->first(); // 1
$last = $collection->last(); // 5
$isEmpty = $collection->isEmpty(); // false

// Map and transform items
$doubled = $collection->map(function ($item) {
    return $item * 2;
}); // [2, 4, 6, 8, 10]

// Filter items
$even = $collection->filter(function ($item) {
    return $item % 2 === 0;
}); // [2 => 2, 4 => 4]

// Filtering by key-value pairs
$admins = $users->where('role', 'admin'); // Only users with role=admin

// Pluck values from arrays or objects
$users = collect([
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25]
]);
$names = $users->pluck('name'); // ['John', 'Jane']

// Sorting
$sorted = collect([3, 1, 5, 2, 4])->sort(); // [1, 2, 3, 4, 5]
$sortedByAge = $users->sortBy('age'); // Jane first, then John

// Aggregation methods
$sum = $collection->sum(); // 15
$avg = $collection->avg(); // 3
$min = $collection->min(); // 1
$max = $collection->max(); // 5
$median = $collection->median(); // 3
$mode = $collection->mode(); // [3] (most frequent value)

// Collection manipulation
$collection->push(6); // Add to end
$collection->prepend(0); // Add to beginning 
$first = $collection->shift(); // Remove and return first item
$last = $collection->pop(); // Remove and return last item

// Chunking
$chunks = $collection->chunk(2); // [[1,2], [3,4], [5]]

// Unique values
$unique = collect([1, 1, 2, 2, 3])->unique(); // [1, 2, 3]

// Grouping
$grouped = $collection->groupBy(function ($item) {
    return $item % 2 === 0 ? 'even' : 'odd';
}); // ['odd' => [1, 3, 5], 'even' => [2, 4]]

// Take specific number of items
$firstThree = $collection->take(3); // [1, 2, 3]
$lastTwo = $collection->take(-2); // [4, 5]

// Merge collections
$merged = $collection->merge([6, 7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8]

// Only or except specific keys
$only = collect(['a' => 1, 'b' => 2, 'c' => 3])->only(['a', 'c']); // ['a' => 1, 'c' => 3]
$except = collect(['a' => 1, 'b' => 2, 'c' => 3])->except(['b']); // ['a' => 1, 'c' => 3]

// Advanced operations
$times = Collection::times(4); // [1, 2, 3, 4]
$times = Collection::times(4, function($n) { return $n * 2; }); // [2, 4, 6, 8] 

$partitioned = $collection->partition(function ($i) { return $i > 3; }); // [[4, 5], [1, 2, 3]]
$random = $collection->random(); // Random item from collection
$random = $collection->random(2); // Collection with 2 random items

$crossJoin = collect([1, 2])->crossJoin(['a', 'b']); // [[1,'a'], [1,'b'], [2,'a'], [2,'b']]
$padded = collect([1, 2])->pad(5, 0); // [1, 2, 0, 0, 0]
$dotted = collect(['foo' => ['bar' => 'baz']])->dot(); // ['foo.bar' => 'baz']
$flipped = collect(['name' => 'taylor'])->flip(); // ['taylor' => 'name']
$page = $collection->forPage(2, 2); // [3, 4] (items for page 2, 2 per page)

// Chaining methods
$result = $collection
    ->filter(function ($item) { return $item > 2; })
    ->map(function ($item) { return $item * 10; })
    ->take(2); // [30, 40]

Collection Debugging

The Collection class includes a powerful debugging toolset:

// Get a debugger instance
$debugger = $collection->debug();

// Or use the helper function
$debugger = collection_debug([1, 2, 3]);

// Dump collection and continue
$collection->debug()->dump();

// Dump as JSON
$collection->debug()->dumpJson();

// Print as a formatted table
$collection->debug()->table();

// Count value occurrences
$collection->debug()->countValues(); // For simple collections
$users->debug()->countValues('role'); // For associative collections

// Get statistics
$numbers->debug()->stats(); // Count, sum, avg, min, max, median, etc.

// Chain with other collection methods
$users
    ->where('role', 'admin')
    ->debug()->dump() // Dump admins
    ->pluck('name')
    ->debug()->table(); // Display admin names in a table

Run the included examples to see these features in action:

php run-collection-example.php
php run-collection-debug-example.php
php run-array-example.php
php run-color-example.php

Hash & Cryptography

Secure password hashing and cryptographic functionality:

use Scriptmancer\Support\Hash;

// Hash a password
$hashed = Hash::make('my-password');

// Verify a password
$isValid = Hash::check('my-password', $hashed);

// Check if a hash needs rehashing
$needsRehash = Hash::needsRehash($hashed);

// Adjust the default cost factor
Hash::setRounds(12); // Higher cost = more secure but slower

// Generate random strings
$random = Hash::random(16); // 16 character random string
$token = Hash::token(40); // 40 character secure token

// Create HMAC
$hmac = Hash::hmac('message', 'key', 'sha256');

// Hash with different algorithms
$sha256 = Hash::digest('message', 'sha256');
$md5 = Hash::digest('message', 'md5');

// Generate UUID (version 4)
$uuid = Hash::uuid(); // e.g. 550e8400-e29b-41d4-a716-446655440000

// Use the helper function
$hashed = hash_value('password');

Run the hash example:

php run-hash-example.php

Advanced Cryptography with OpenSSL

In addition to basic hashing, the Hash class also provides OpenSSL encryption capabilities:

use Scriptmancer\Support\Hash;

// Encrypt and decrypt data
$key = Hash::generateKey(); // Generate a secure key
$encrypted = Hash::encrypt('Secret message', $key);
$decrypted = Hash::decrypt($encrypted, $key);

// Get available ciphers
$ciphers = Hash::getAvailableCiphers();

// Use a custom cipher
$encrypted = Hash::encrypt('Secret message', $key, 'AES-128-CBC');

// Change the default cipher
Hash::setCipher('AES-128-CBC');

// Create a hash of a file
$fileHash = Hash::file('/path/to/file', 'sha256');

Pipeline Pattern

The Pipeline pattern allows you to pass an object through a series of stages or transformations:

use Scriptmancer\Support\Pipeline;

// Basic pipeline with closures
$result = Pipeline::make('Hello')
    ->through([
        function ($string, $next) {
            return $next($string . ', ');
        },
        function ($string, $next) {
            return $next($string . 'World');
        },
        function ($string, $next) {
            return $next($string . '!');
        },
    ])
    ->thenReturn();
// Result: "Hello, World!"

// Using pipe classes
class UppercasePipe
{
    public function handle($data, $next)
    {
        return $next(strtoupper($data));
    }
}

$result = Pipeline::make('hello')
    ->through([
        UppercasePipe::class,
        // Other pipes...
    ])
    ->thenReturn();

// Use the pipeline helper
$result = pipeline([1, 2, 3, 4, 5])
    ->through([
        function ($numbers, $next) {
            return $next(array_filter($numbers, fn($n) => $n % 2 === 0));
        },
        function ($numbers, $next) {
            return $next(array_map(fn($n) => $n * $n, $numbers));
        },
    ])
    ->thenReturn();

// Use a custom method name for pipe classes
$result = pipeline(10)
    ->through([MyPipe::class])
    ->via('process')  // Use 'process' method instead of default 'handle'
    ->thenReturn();

Run the pipeline example:

php run-pipeline-example.php

Date Handling

Work with dates in an immutable way using DateObject:

// Create a date object
$date = new \Scriptmancer\Support\DateObject();
// Or use the helper function
$date = date_obj();
$specificDate = date_obj('2023-01-15');

// Perform operations that return new instances
$tomorrow = $date->addDays(1);
$nextMonth = $date->addMonths(1);

// Check date conditions
$isWeekend = $date->isWeekend();
$isBetween = $date->isBetween($start, $end);

// Static creation methods
$today = \Scriptmancer\Support\DateObject::today();
$yesterday = \Scriptmancer\Support\DateObject::yesterday();

String Manipulation

Fluent string manipulation with the Stringable class:

// Create a string object
$string = new \Scriptmancer\Support\Stringable('Hello, World!');
// Or use the helper function
$string = str('Hello, World!');
// Or use the static method
$string = \Scriptmancer\Support\Stringable::of('Hello, World!');

// Method chaining
$result = str('  HELLO, WORLD!  ')
    ->trim()
    ->lower()
    ->replace('world', 'PHP')
    ->title();
// "Hello, PHP!"

// Transformations
$camelCase = str('hello_world')->camel(); // "helloWorld"
$snakeCase = str('helloWorld')->snake(); // "hello_world"
$kebabCase = str('helloWorld')->kebab(); // "hello-world"

// String checks
$contains = str('Hello, World!')->contains('World'); // true
$startsWith = str('Hello, World!')->startsWith('Hello'); // true
$endsWith = str('Hello, World!')->endsWith('!'); // true

Array Utilities

A comprehensive set of array manipulation utilities:

use Scriptmancer\Support\Arr;

// Getting and setting values
$value = Arr::get($array, 'key', 'default');
Arr::set($array, 'key', 'value');

// Array operations
$first = Arr::first($array);
$last = Arr::last($array);
$keys = Arr::keys($array);
$values = Arr::values($array);

// Functional operations
$mapped = Arr::map($array, fn($item) => $item * 2);
$filtered = Arr::filter($array, fn($item) => $item > 5);
$reduced = Arr::reduce($array, fn($carry, $item) => $carry + $item, 0);

// Array transformations
$unique = Arr::unique($array);
$sorted = Arr::sort($array);
$reversed = Arr::reverse($array);
$grouped = Arr::groupBy($array, 'key');
$wrapped = Arr::wrap('value'); // ['value'] - wraps non-arrays in an array

// Advanced operations
$contains = Arr::contains($array, 'value');
$every = Arr::every($array, fn($item) => $item > 0);
$some = Arr::some($array, fn($item) => $item > 10);

// Locale-specific string sorting
$turkish_words = ['şeker', 'armut', 'çilek', 'elma', 'üzüm', 'ıspanak'];
$sorted = Arr::string_sort($turkish_words, 'tr_TR'); // Sort using Turkish locale

// Sorting arrays of objects or associative arrays by field
$people = [
    ['name' => 'Şule', 'age' => 30],
    ['name' => 'Ahmet', 'age' => 25],
    ['name' => 'Çiğdem', 'age' => 28]
];
$sortedByName = Arr::string_sort($people, 'tr_TR', 'name');

// Sorting associative arrays by key
$months = [
    'Şubat' => 2,
    'Ocak' => 1,
    'Mart' => 3
];
$sortedMonths = Arr::string_sort_by_key($months, 'tr_TR');

Color Utilities

Manipulate and convert colors with the Color utility class:

use Scriptmancer\Support\Color;

// Expand short hex
Color::expandHex('#3aF'); // '33aaFF'

// Convert to RGB/RGBA strings
Color::toRgbString('#3498db'); // 'rgb(52, 152, 219)'
Color::toRgbaString('#3498db'); // 'rgba(52, 152, 219, 0)'

// Convert to HSL/HSLA strings
Color::toHslString('rgb(52,152,219)');
Color::toHslaString('rgb(52,152,219)');

// Lighten/Darken
Color::lighten('#3498db', 0.2); // Lighten 20%
Color::darken('#3498db', 0.2); // Darken 20%

// Invert
Color::invert('#3498db');

// Blend two colors
Color::blend('#3498db', '#e74c3c', 0.5);

// Get best contrast color (black/white)
Color::getContrastColor('#222'); // '#FFFFFF'

// Generate a random color
Color::random();

// Convert between formats
Color::toHex('rgb(52,152,219)');
Color::toRgb('#3498db');
Color::toHsl('#3498db');

Run the color example to see these features:

php run-color-example.php

Number Formatting

Format numbers with proper locale-specific formatting:

// Create a number formatter
$number = new \Scriptmancer\Support\Number('tr_TR');
// Or use the helper function
$number = number();
// Or specify a different locale
$english = number('en_US');
$german = number('de_DE');

// Basic number formatting
echo $number->format(1234.56); // 1.234,56
echo $number->format(1234.56, 0); // 1.235
echo $number->format(1234.56, 3); // 1.234,560

// Currency formatting
echo $number->currency(1234.56); // ₺1.234,56
echo $number->currency(1234.56, 'USD'); // $1.234,56
echo $english->currency(1234.56, 'EUR'); // €1,234.56

// Percentage formatting
echo $number->percent(0.75); // %75
echo $english->percent(0.75); // 75%

// Short form for large numbers
echo $number->shortForm(1500); // 1,5K
echo $number->shortForm(1500000); // 1,5M
echo $number->shortForm(1500000000); // 1,5B

// Spelling out numbers in words
echo $number->spellOut(42); // kırk iki
echo $english->spellOut(42); // forty-two

// Ordinal numbers
echo $number->ordinal(1); // 1.
echo $english->ordinal(1); // 1st

// Roman numerals
echo $number->roman(1984); // MCMLXXXIV

// Static methods
echo Number::isEven(42); // true
echo Number::isOdd(43); // true

Requirements

  • PHP 8.2 or higher
  • Kint (automatically required through Composer)
  • PHP Intl extension (for locale-specific string sorting and number formatting)

License

MIT