Initial Drupal 11 with DDEV setup
This commit is contained in:
24
vendor/phootwork/collection/.github/workflows/release.yml
vendored
Normal file
24
vendor/phootwork/collection/.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Create a release when a version tag is pushed
|
||||
name: Create Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v1
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body: For changes in this release please see https://github.com/phootwork/phootwork/releases/tag/${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
3
vendor/phootwork/collection/.gitignore
vendored
Normal file
3
vendor/phootwork/collection/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
composer.phar
|
||||
composer.lock
|
||||
vendor/
|
||||
61
vendor/phootwork/collection/AbstractCollection.php
vendored
Normal file
61
vendor/phootwork/collection/AbstractCollection.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use phootwork\lang\AbstractArray;
|
||||
|
||||
/**
|
||||
* AbstractCollection providing implementation for the Collection interface.
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
abstract class AbstractCollection extends AbstractArray implements Collection {
|
||||
/**
|
||||
* Remove all elements from the collection.
|
||||
*/
|
||||
public function clear(): void {
|
||||
$this->array = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function rewind(): void {
|
||||
reset($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function current(): mixed {
|
||||
return current($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function key(): int|string|null {
|
||||
return key($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function next(): void {
|
||||
next($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function valid(): bool {
|
||||
return key($this->array) !== null;
|
||||
}
|
||||
}
|
||||
43
vendor/phootwork/collection/AbstractList.php
vendored
Normal file
43
vendor/phootwork/collection/AbstractList.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use phootwork\lang\Comparator;
|
||||
use phootwork\lang\parts\EachPart;
|
||||
use phootwork\lang\parts\ReducePart;
|
||||
use phootwork\lang\parts\RemovePart;
|
||||
use phootwork\lang\parts\ReversePart;
|
||||
|
||||
/**
|
||||
* Abstract class for all list-like collections
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
abstract class AbstractList extends AbstractCollection {
|
||||
use EachPart;
|
||||
use ReducePart;
|
||||
use RemovePart;
|
||||
use ReversePart;
|
||||
|
||||
/**
|
||||
* Sorts the collection in reverse order
|
||||
*
|
||||
* @see #sort
|
||||
* @see #reverse
|
||||
*
|
||||
* @param Comparator|callable|null $cmp
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reverseSort(Comparator|callable|null $cmp = null): self {
|
||||
return $this->sort($cmp)->reverse();
|
||||
}
|
||||
}
|
||||
136
vendor/phootwork/collection/ArrayList.php
vendored
Normal file
136
vendor/phootwork/collection/ArrayList.php
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
use phootwork\lang\parts\AccessorsPart;
|
||||
use phootwork\lang\parts\AddPart;
|
||||
use phootwork\lang\parts\IndexFindersPart;
|
||||
use phootwork\lang\parts\InsertPart;
|
||||
|
||||
/**
|
||||
* Represents a List
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
class ArrayList extends AbstractList {
|
||||
use AccessorsPart {
|
||||
get as traitGet;
|
||||
}
|
||||
use AddPart;
|
||||
use IndexFindersPart {
|
||||
indexOf as traitIndexOf;
|
||||
findLastIndex as traitFindLastIndex;
|
||||
findIndex as traitFindIndex;
|
||||
}
|
||||
use InsertPart;
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*/
|
||||
public function __construct(array|Iterator $collection = []) {
|
||||
/** @var mixed $element */
|
||||
foreach ($collection as $element) {
|
||||
$this->add($element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an element from the list by its index.
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public function removeByIndex(int $index): self {
|
||||
if (isset($this->array[$index])) {
|
||||
unset($this->array[$index]);
|
||||
|
||||
if (!array_is_list($this->array)) {
|
||||
$this->array = array_values($this->array);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element at the given index (or null if the index isn't present)
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(int $index): mixed {
|
||||
return $this->traitGet($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the given element or null if the element can't be found
|
||||
*
|
||||
* @param mixed $element
|
||||
*
|
||||
* @return int|null the index for the given element
|
||||
*/
|
||||
public function indexOf(mixed $element): ?int {
|
||||
$index = $this->traitIndexOf($element);
|
||||
|
||||
return $index === null ? $index : (int) $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the index for the last element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return int|null the index or null if it hasn't been found
|
||||
*/
|
||||
public function findLastIndex(mixed ...$arguments): ?int {
|
||||
$lastIndex = $this->traitFindLastIndex(...$arguments);
|
||||
|
||||
return $lastIndex === null ? $lastIndex : (int) $lastIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the index for the first element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return int|null the index or null if it hasn't been found
|
||||
*/
|
||||
public function findIndex(mixed ...$arguments): ?int {
|
||||
$index = $this->traitFindIndex(...$arguments);
|
||||
|
||||
return $index === null ? $index : (int) $index;
|
||||
}
|
||||
}
|
||||
54
vendor/phootwork/collection/Collection.php
vendored
Normal file
54
vendor/phootwork/collection/Collection.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
/**
|
||||
* Collection interface
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
interface Collection extends \Iterator {
|
||||
/**
|
||||
* Resets the collection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear(): void;
|
||||
|
||||
/**
|
||||
* Checks whether this collection is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool;
|
||||
|
||||
/**
|
||||
* Checks whether the given element is in this collection
|
||||
*
|
||||
* @param mixed $element
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(mixed $element): bool;
|
||||
|
||||
/**
|
||||
* Returns the amount of elements in this collection
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function size(): int;
|
||||
|
||||
/**
|
||||
* Returns the collection as an array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array;
|
||||
}
|
||||
135
vendor/phootwork/collection/CollectionUtils.php
vendored
Normal file
135
vendor/phootwork/collection/CollectionUtils.php
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* CollectionUtils help to transform data recursively into collections.
|
||||
*
|
||||
* It must be mentioned the API is experimental and may change. Please
|
||||
* report to the issue tracker.
|
||||
*/
|
||||
class CollectionUtils {
|
||||
/**
|
||||
* Returns a proper collection for the given array (also transforms nested collections)
|
||||
* (experimental API)
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*
|
||||
* @return Map|ArrayList the collection
|
||||
*
|
||||
* @psalm-suppress MixedReturnStatement `self::toCollection()` returns a collection if the input
|
||||
* is an array or Iterator
|
||||
* @psalm-suppress MixedInferredReturnType
|
||||
*/
|
||||
public static function fromCollection(array|Iterator $collection): Map|ArrayList {
|
||||
return self::toCollection($collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function toCollection(mixed $data): mixed {
|
||||
// prepare normal array
|
||||
if (!($data instanceof Iterator)) {
|
||||
/** @var mixed $data */
|
||||
$data = json_decode(json_encode($data));
|
||||
}
|
||||
|
||||
// check if we can transform it into a collection or just return as is
|
||||
if (!(is_array($data) || $data instanceof Iterator || $data instanceof stdClass)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
// check we have a list
|
||||
if (is_array($data) || $data instanceof AbstractList) {
|
||||
return self::toList($data);
|
||||
}
|
||||
|
||||
// everything else must be a map
|
||||
return self::toMap($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively transforms data into a map (on the first level, deeper levels
|
||||
* transformed to an appropriate collection) (experimental API)
|
||||
*
|
||||
* @param array|Iterator|stdClass $collection
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
public static function toMap(Iterator|array|stdClass $collection): Map {
|
||||
if ($collection instanceof stdClass) {
|
||||
/** @var array $collection */
|
||||
$collection = json_decode(json_encode($collection), true);
|
||||
}
|
||||
|
||||
$map = new Map();
|
||||
/**
|
||||
* @var string $k
|
||||
* @var string $v
|
||||
*/
|
||||
foreach ($collection as $k => $v) {
|
||||
$map->set($k, self::toCollection($v));
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively transforms data into a list (on the first level, deeper levels
|
||||
* transformed to an appropriate collection) (experimental API)
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*
|
||||
* @return ArrayList
|
||||
*/
|
||||
public static function toList(Iterator|array $collection): ArrayList {
|
||||
$list = new ArrayList();
|
||||
/** @var mixed $v */
|
||||
foreach ($collection as $v) {
|
||||
$list->add(self::toCollection($v));
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively exports a collection to an array
|
||||
*
|
||||
* @param mixed $collection
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public static function toArrayRecursive(mixed $collection): array {
|
||||
$arr = $collection;
|
||||
if (is_object($collection) && method_exists($collection, 'toArray')) {
|
||||
$arr = $collection->toArray();
|
||||
}
|
||||
|
||||
/** @var array $arr */
|
||||
return array_map(
|
||||
function (mixed $v): mixed {
|
||||
if (is_object($v) && method_exists($v, 'toArray')) {
|
||||
return static::toArrayRecursive($v);
|
||||
}
|
||||
|
||||
return $v;
|
||||
},
|
||||
$arr
|
||||
);
|
||||
}
|
||||
}
|
||||
22
vendor/phootwork/collection/LICENSE
vendored
Normal file
22
vendor/phootwork/collection/LICENSE
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 - 2021 Thomas Gossmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
268
vendor/phootwork/collection/Map.php
vendored
Normal file
268
vendor/phootwork/collection/Map.php
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
use phootwork\lang\AbstractArray;
|
||||
use phootwork\lang\Comparator;
|
||||
use phootwork\lang\parts\SortAssocPart;
|
||||
use phootwork\lang\Text;
|
||||
|
||||
/**
|
||||
* Represents a Map
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
class Map extends AbstractCollection implements \ArrayAccess {
|
||||
use SortAssocPart;
|
||||
|
||||
/**
|
||||
* Creates a new Map
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*/
|
||||
public function __construct(array|Iterator $collection = []) {
|
||||
$this->setAll($collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an element with the given key on that map
|
||||
*
|
||||
* @param string|int|Text $key
|
||||
* @param mixed $element
|
||||
*
|
||||
* @return Map $this
|
||||
*/
|
||||
public function set(string|int|Text $key, mixed $element): self {
|
||||
$key = is_int($key) ? $key : (string) $key;
|
||||
$this->array[$key] = $element;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element for the given key
|
||||
*
|
||||
* @param string|int|Text $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string|int|Text $key): mixed {
|
||||
$key = is_int($key) ? $key : (string) $key;
|
||||
|
||||
return $this->array[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the given value or null if not found
|
||||
*
|
||||
* @param mixed $value the value
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getKey(mixed $value): ?string {
|
||||
/**
|
||||
* @var string $k
|
||||
* @var mixed $v
|
||||
*/
|
||||
foreach ($this->array as $k => $v) {
|
||||
if ($v === $value) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets many elements on that map
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*
|
||||
* @return Map $this
|
||||
*/
|
||||
public function setAll(array|Iterator $collection): self {
|
||||
/**
|
||||
* @var string $key
|
||||
* @var mixed $element
|
||||
*/
|
||||
foreach ($collection as $key => $element) {
|
||||
$this->set($key, $element);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns an element from the map by the given key. Returns null if the key
|
||||
* does not exist.
|
||||
*
|
||||
* @param string|Text $key
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function remove(string|Text $key): self {
|
||||
if (isset($this->array[(string) $key])) {
|
||||
unset($this->array[(string) $key]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all keys as Set
|
||||
*
|
||||
* @return Set the map's keys
|
||||
*/
|
||||
public function keys(): Set {
|
||||
return new Set(array_keys($this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all values as ArrayList
|
||||
*
|
||||
* @return ArrayList the map's values
|
||||
*/
|
||||
public function values(): ArrayList {
|
||||
return new ArrayList(array_values($this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the key exist.
|
||||
*
|
||||
* @param string|Text $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(string|Text $key): bool {
|
||||
return isset($this->array[(string) $key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the map
|
||||
*
|
||||
* @param Comparator|callable|null $cmp
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sort(Comparator|callable|null $cmp = null): AbstractArray {
|
||||
return $this->sortAssoc($cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates the map and calls the callback function with the current key and value as parameters
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function each(callable $callback): void {
|
||||
/**
|
||||
* @var string $key
|
||||
* @var mixed $value
|
||||
*/
|
||||
foreach ($this->array as $key => $value) {
|
||||
$callback($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the collection with a given callback and returns the key for the first element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return mixed|null the key or null if it hasn't been found
|
||||
*/
|
||||
public function findKey(mixed ...$arguments) {
|
||||
/** @var mixed $index */
|
||||
$index = count($arguments) === 1 ? $this->find($arguments[0]) : $this->find($arguments[0], $arguments[1]);
|
||||
|
||||
return $this->getKey($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the collection with a given callback and returns the key for the last element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return mixed|null the key or null if it hasn't been found
|
||||
*/
|
||||
public function findLastKey(mixed ...$arguments) {
|
||||
/** @var mixed $index */
|
||||
$index = count($arguments) === 1 ? $this->findLast($arguments[0]) : $this->findLast($arguments[0], $arguments[1]);
|
||||
|
||||
return $this->getKey($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void {
|
||||
/** @var string|null $offset */
|
||||
if ($offset !== null) {
|
||||
$this->array[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetExists(mixed $offset): bool {
|
||||
/** @var string $offset */
|
||||
return isset($this->array[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetUnset(mixed $offset): void {
|
||||
/** @var string $offset */
|
||||
unset($this->array[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetGet(mixed $offset): mixed {
|
||||
/** @var string $offset */
|
||||
return isset($this->array[$offset]) ? $this->array[$offset] : null;
|
||||
}
|
||||
}
|
||||
65
vendor/phootwork/collection/Queue.php
vendored
Normal file
65
vendor/phootwork/collection/Queue.php
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
|
||||
/**
|
||||
* Represents a Queue
|
||||
*
|
||||
* FIFO - first in first out
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
class Queue extends AbstractList {
|
||||
/**
|
||||
* Creates a new Queue
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*/
|
||||
public function __construct(array|Iterator $collection = []) {
|
||||
$this->enqueue(...$collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues an element
|
||||
*
|
||||
* @param mixed ...$elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function enqueue(mixed ...$elements): self {
|
||||
array_unshift($this->array, ...$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element at the head or null if the queue is empty but doesn't remove that element
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function peek(): mixed {
|
||||
if ($this->size() > 0) {
|
||||
return $this->array[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns the element at the head or null if the is empty
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function poll(): mixed {
|
||||
return array_shift($this->array);
|
||||
}
|
||||
}
|
||||
59
vendor/phootwork/collection/README.md
vendored
Normal file
59
vendor/phootwork/collection/README.md
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
# PHP Collections library
|
||||
|
||||

|
||||
[](https://scrutinizer-ci.com/g/phootwork/phootwork/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/phootwork/phootwork/?branch=master)
|
||||
[](https://packagist.org/packages/phootwork/collection)
|
||||
[](https://packagist.org/packages/phootwork/collection)
|
||||
[](https://packagist.org/packages/phootwork/collection)
|
||||
|
||||
PHP Collections library which contains ArrayList, Set, Map, Queue & Stack.
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide collections for php
|
||||
- Inspired by java `java.util.Collection`
|
||||
- Functional sugar (map, filter, reduce, ...)
|
||||
|
||||
## Installation
|
||||
|
||||
Installation via composer:
|
||||
|
||||
```
|
||||
composer require phootwork/collection
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
[https://phootwork.github.io/collection](https://phootwork.github.io/collection)
|
||||
|
||||
## Running tests
|
||||
|
||||
This package is a part of the Phootwork library. In order to run the test suite, you have to download the full library.
|
||||
|
||||
```
|
||||
git clone https://github.com/phootwork/phootwork
|
||||
```
|
||||
Then install the dependencies via composer:
|
||||
|
||||
```
|
||||
composer install
|
||||
```
|
||||
Now, run the *collection* test suite:
|
||||
|
||||
```
|
||||
vendor/bin/phpunit --testsuite collection
|
||||
```
|
||||
If you want to run the whole library tests, simply run:
|
||||
|
||||
```
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
|
||||
## Contact
|
||||
|
||||
Report issues at the github [Issue Tracker](https://github.com/phootwork/phootwork/issues).
|
||||
|
||||
## Changelog
|
||||
|
||||
Refer to [Releases](https://github.com/phootwork/phootwork/releases)
|
||||
46
vendor/phootwork/collection/Set.php
vendored
Normal file
46
vendor/phootwork/collection/Set.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
|
||||
/**
|
||||
* Represents a Set
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
class Set extends AbstractList {
|
||||
/**
|
||||
* Creates a new Set
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*/
|
||||
public function __construct(array|Iterator $collection = []) {
|
||||
$this->add(...$collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to that set
|
||||
*
|
||||
* @param mixed ...$elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add(mixed ...$elements): self {
|
||||
/** @var mixed $element */
|
||||
foreach ($elements as $element) {
|
||||
if (!in_array($element, $this->array, true)) {
|
||||
$this->array[$this->size()] = $element;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
59
vendor/phootwork/collection/Stack.php
vendored
Normal file
59
vendor/phootwork/collection/Stack.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\collection;
|
||||
|
||||
use Iterator;
|
||||
use phootwork\lang\parts\PopPart;
|
||||
|
||||
/**
|
||||
* Represents a Stack
|
||||
*
|
||||
* FILO - first in last out
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
class Stack extends AbstractList {
|
||||
use PopPart;
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList
|
||||
*
|
||||
* @param array|Iterator $collection
|
||||
*/
|
||||
public function __construct(array|Iterator $collection = []) {
|
||||
$this->push(...$collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes an element onto the stack
|
||||
*
|
||||
* @param mixed ...$elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function push(mixed ...$elements): self {
|
||||
array_push($this->array, ...$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element at the head or null if the stack is empty but doesn't remove that element
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function peek(): mixed {
|
||||
if ($this->size() > 0) {
|
||||
return $this->array[$this->size() - 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
37
vendor/phootwork/collection/composer.json
vendored
Normal file
37
vendor/phootwork/collection/composer.json
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name" : "phootwork/collection",
|
||||
"type" : "library",
|
||||
"description" : "The phootwork library fills gaps in the php language and provides better solutions than the existing ones php offers.",
|
||||
"authors" : [{
|
||||
"name" : "Thomas Gossmann",
|
||||
"homepage" : "http://gos.si"
|
||||
}
|
||||
],
|
||||
"license" : "MIT",
|
||||
"keywords" : [
|
||||
"Text object",
|
||||
"Array object",
|
||||
"collection",
|
||||
"collections",
|
||||
"list",
|
||||
"set",
|
||||
"map",
|
||||
"queue",
|
||||
"stack",
|
||||
"xml",
|
||||
"json"
|
||||
],
|
||||
"support" : {
|
||||
"issues" : "https://github.com/phootwork/phootwork/issues"
|
||||
},
|
||||
"autoload" : {
|
||||
"psr-4" : {
|
||||
"phootwork\\collection\\" : ""
|
||||
}
|
||||
},
|
||||
"require" : {
|
||||
"php" : ">=8.0",
|
||||
"phootwork/lang" : "^3.0"
|
||||
},
|
||||
"homepage" : "https://phootwork.github.io/collection/"
|
||||
}
|
||||
24
vendor/phootwork/lang/.github/workflows/release.yml
vendored
Normal file
24
vendor/phootwork/lang/.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Create a release when a version tag is pushed
|
||||
name: Create Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v1
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
body: For changes in this release please see https://github.com/phootwork/phootwork/releases/tag/${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
3
vendor/phootwork/lang/.gitignore
vendored
Normal file
3
vendor/phootwork/lang/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
composer.phar
|
||||
composer.lock
|
||||
vendor/
|
||||
300
vendor/phootwork/lang/AbstractArray.php
vendored
Normal file
300
vendor/phootwork/lang/AbstractArray.php
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
/**
|
||||
* Superclass containing property and methods shared between
|
||||
* `phootwork\lang\ArrayObject` and `phootwork\class\AbstractCollection`
|
||||
*
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
abstract class AbstractArray implements \Countable {
|
||||
/** @var array */
|
||||
protected array $array = [];
|
||||
|
||||
abstract public function __construct(array $contents = []);
|
||||
|
||||
/**
|
||||
* Counts the array
|
||||
*
|
||||
* @return int the amount of items
|
||||
*/
|
||||
public function count(): int {
|
||||
return count($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the array.
|
||||
* Alias of `count`
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function size(): int {
|
||||
return $this->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress UnsafeInstantiation
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function __clone() {
|
||||
return new static($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given element is in this array
|
||||
*
|
||||
* @param mixed $element
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(mixed $element): bool {
|
||||
return in_array($element, $this->array, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this array is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool {
|
||||
return count($this->array) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the first element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return mixed the found element or null if it hasn't been found
|
||||
*
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedFunctionCall
|
||||
*/
|
||||
public function find(mixed ...$arguments): mixed {
|
||||
foreach ($this->array as $element) {
|
||||
$return = count($arguments) === 1 ? $arguments[0]($element) : $arguments[1]($element, $arguments[0]);
|
||||
|
||||
if ($return) {
|
||||
return $element;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the last element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return mixed the found element or null if it hasn't been found
|
||||
*
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedFunctionCall
|
||||
*/
|
||||
public function findLast(mixed ...$arguments): mixed {
|
||||
$reverse = array_reverse($this->array, true);
|
||||
foreach ($reverse as $element) {
|
||||
$return = count($arguments) === 1 ? $arguments[0]($element) : $arguments[1]($element, $arguments[0]);
|
||||
|
||||
if ($return) {
|
||||
return $element;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns all matching elements.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param mixed ...$arguments
|
||||
*
|
||||
* @return static an ArrayObject or a collection of found elements
|
||||
*
|
||||
* @psalm-suppress UnsafeInstantiation
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedFunctionCall
|
||||
*/
|
||||
public function findAll(mixed ...$arguments): static {
|
||||
$array = [];
|
||||
|
||||
foreach ($this->array as $k => $element) {
|
||||
$return = count($arguments) === 1 ? $arguments[0]($element) : $arguments[1]($element, $arguments[0]);
|
||||
|
||||
if ($return) {
|
||||
$array[$k] = $element;
|
||||
}
|
||||
}
|
||||
|
||||
return new static($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array for query using the callback function on each element
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - search($query, callback)
|
||||
* - search(callback)
|
||||
*
|
||||
* @param mixed ...$arguments
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-suppress MixedFunctionCall
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public function search(mixed ...$arguments): bool {
|
||||
foreach ($this->array as $element) {
|
||||
$return = count($arguments) === 1 ? $arguments[0]($element) : $arguments[1]($element, $arguments[0]);
|
||||
|
||||
if ($return) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the php array type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array {
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the array
|
||||
*
|
||||
* @param Comparator|callable|null $cmp
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sort(Comparator|callable|null $cmp = null): self {
|
||||
$this->doSort($this->array, 'usort', 'sort', $cmp);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal sort function
|
||||
*
|
||||
* @param array $array the array on which is operated on
|
||||
* @param callable $usort the sort function for user passed $cmd
|
||||
* @param callable $sort the default sort function
|
||||
* @param Comparator|callable|null $cmp the compare function
|
||||
*/
|
||||
protected function doSort(array & $array, callable $usort, callable $sort, Comparator|callable|null $cmp = null): void {
|
||||
if (is_callable($cmp)) {
|
||||
$usort($array, $cmp);
|
||||
} elseif ($cmp instanceof Comparator) {
|
||||
$usort(
|
||||
$array,
|
||||
function (mixed $a, mixed $b) use ($cmp): int {
|
||||
return $cmp->compare($a, $b);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$sort($array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether all elements in the array pass the test implemented by the provided function.
|
||||
*
|
||||
* Returns <code>true</code> for an empty array.
|
||||
*
|
||||
* @param callable(mixed, mixed): scalar $callback
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function every(callable $callback): bool {
|
||||
return $this->count() === count(array_filter($this->array, $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether at least one element in the array passes the test implemented by the provided function.
|
||||
*
|
||||
* Returns <code>false</code> for an empty array.
|
||||
*
|
||||
* @param callable(mixed, mixed): scalar $callback
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function some(callable $callback): bool {
|
||||
return count(array_filter($this->array, $callback)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters elements using a callback function
|
||||
*
|
||||
* @param callable(mixed, mixed): scalar $callback the filter function
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @psalm-suppress UnsafeInstantiation
|
||||
*/
|
||||
public function filter(callable $callback): self {
|
||||
return new static(array_filter($this->array, $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the callback to the elements
|
||||
*
|
||||
* @param callable $callback the applied callback function
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @psalm-suppress UnsafeInstantiation
|
||||
*/
|
||||
public function map(callable $callback): self {
|
||||
return new static(array_map($callback, $this->array));
|
||||
}
|
||||
}
|
||||
281
vendor/phootwork/lang/ArrayObject.php
vendored
Normal file
281
vendor/phootwork/lang/ArrayObject.php
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
use phootwork\lang\parts\AccessorsPart;
|
||||
use phootwork\lang\parts\AddPart;
|
||||
use phootwork\lang\parts\EachPart;
|
||||
use phootwork\lang\parts\IndexFindersPart;
|
||||
use phootwork\lang\parts\InsertPart;
|
||||
use phootwork\lang\parts\PopPart;
|
||||
use phootwork\lang\parts\ReducePart;
|
||||
use phootwork\lang\parts\RemovePart;
|
||||
use phootwork\lang\parts\ReversePart;
|
||||
use phootwork\lang\parts\SortAssocPart;
|
||||
|
||||
class ArrayObject extends AbstractArray implements \ArrayAccess, \Countable, \IteratorAggregate, \Serializable, Arrayable {
|
||||
use AccessorsPart;
|
||||
use AddPart;
|
||||
use EachPart;
|
||||
use IndexFindersPart;
|
||||
use InsertPart;
|
||||
use PopPart;
|
||||
use ReducePart;
|
||||
use RemovePart;
|
||||
use ReversePart;
|
||||
use SortAssocPart;
|
||||
|
||||
public function __construct(array $contents = []) {
|
||||
$this->array = $contents;
|
||||
}
|
||||
|
||||
public function __serialize(): array {
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
public function __unserialize(array $data): void {
|
||||
$this->array = $data;
|
||||
}
|
||||
|
||||
public function getIterator(): \ArrayIterator {
|
||||
return new \ArrayIterator($this->array);
|
||||
}
|
||||
|
||||
public function serialize(): string {
|
||||
return serialize($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MethodSignatureMismatch `\Serializable::unserialize` return `void` but we want fluid interface.
|
||||
* @psalm-suppress MixedAssignment if `unserialize($serialized)` can't return an array, this assignment throws
|
||||
* a TypeError exception, which is ok for us
|
||||
*/
|
||||
public function unserialize(string $serialized): self {
|
||||
$this->array = unserialize($serialized);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the array
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clear(): self {
|
||||
$this->array = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// MUTATIONS
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Append one or more elements onto the end of array
|
||||
*
|
||||
* @param array $elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function append(mixed ...$elements): self {
|
||||
array_push($this->array, ...$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend one or more elements to the beginning of the array
|
||||
*
|
||||
* @param array $elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function prepend(mixed ...$elements): self {
|
||||
array_unshift($this->array, ...$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift an element off the beginning of array
|
||||
*
|
||||
* @return mixed the shifted element
|
||||
*/
|
||||
public function shift(): mixed {
|
||||
return array_shift($this->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a portion of the array and replace it with something else
|
||||
*
|
||||
* @param int $offset If offset is positive then the start of removed portion is at that offset from the beginning of the input array. If offset is negative then it starts that far from the end of the input array.
|
||||
* @param int|null $length If length is omitted, removes everything from offset to the end of the array. If length is specified and is positive, then that many elements will be removed. If length is specified and is negative then the end of the removed portion will be that many elements from the end of the array. If length is specified and is zero, no elements will be removed.
|
||||
* @param array $replacement If replacement array is specified, then the removed elements are replaced with elements from this array. If offset and length are such that nothing is removed, then the elements from the replacement array are inserted in the place specified by the offset. Note that keys in replacement array are not preserved. If replacement is just one element it is not necessary to put array() around it, unless the element is an array itself, an object or NULL.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @psalm-suppress PossiblyNullArgument third argument of `array_splice` CAN be null
|
||||
*/
|
||||
public function splice(int $offset, ?int $length = null, array $replacement = []): self {
|
||||
array_splice($this->array, $offset, $length, $replacement);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// SUGAR
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Joins the array with a string
|
||||
*
|
||||
* @param string $glue Defaults to an empty string.
|
||||
*
|
||||
* @return Text
|
||||
* Returns a string containing a string representation of all the array elements in the
|
||||
* same order, with the glue string between each element.
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion
|
||||
*/
|
||||
public function join(string $glue = ''): Text {
|
||||
array_map(
|
||||
function (mixed $element): void {
|
||||
if (!($element === null || is_scalar($element) || $element instanceof \Stringable)) {
|
||||
throw new \TypeError('Can join elements only if scalar, null or \\Stringable');
|
||||
}
|
||||
},
|
||||
$this->array
|
||||
);
|
||||
|
||||
return new Text(implode($glue, $this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a slice of the array
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
* @param bool $preserveKeys
|
||||
*
|
||||
* @return ArrayObject
|
||||
*/
|
||||
public function slice(int $offset, ?int $length = null, bool $preserveKeys = false): self {
|
||||
return new self(array_slice($this->array, $offset, $length, $preserveKeys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges in other values
|
||||
*
|
||||
* @param array ...$toMerge Variable list of arrays to merge.
|
||||
*
|
||||
* @return ArrayObject $this
|
||||
*/
|
||||
public function merge(mixed ...$toMerge): self {
|
||||
$this->array = array_merge($this->array, ...$toMerge);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges in other values, recursively
|
||||
*
|
||||
* @param array ...$toMerge Variable list of arrays to merge.
|
||||
*
|
||||
* @return ArrayObject $this
|
||||
*/
|
||||
public function mergeRecursive(mixed ...$toMerge): self {
|
||||
$this->array = array_merge_recursive($this->array, ...$toMerge);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keys of the array
|
||||
*
|
||||
* @return ArrayObject the keys
|
||||
*/
|
||||
public function keys(): self {
|
||||
return new self(array_keys($this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of the array
|
||||
*
|
||||
* @return ArrayObject the values
|
||||
*/
|
||||
public function values(): self {
|
||||
return new self(array_values($this->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips keys and values
|
||||
*
|
||||
* @return ArrayObject $this
|
||||
*/
|
||||
public function flip(): self {
|
||||
$this->array = array_flip($this->array);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// INTERNALS
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* @param int|string|null $offset
|
||||
* @param mixed $value
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void {
|
||||
if (!is_null($offset)) {
|
||||
$this->array[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $offset
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetExists(mixed $offset): bool {
|
||||
return isset($this->array[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $offset
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetUnset(mixed $offset): void {
|
||||
unset($this->array[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $offset
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function offsetGet(mixed $offset): mixed {
|
||||
return $this->array[$offset] ?? null;
|
||||
}
|
||||
}
|
||||
19
vendor/phootwork/lang/Arrayable.php
vendored
Normal file
19
vendor/phootwork/lang/Arrayable.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
interface Arrayable {
|
||||
/**
|
||||
* Array representation of the object
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array;
|
||||
}
|
||||
24
vendor/phootwork/lang/Comparable.php
vendored
Normal file
24
vendor/phootwork/lang/Comparable.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
interface Comparable {
|
||||
/**
|
||||
* Compares to another object
|
||||
*
|
||||
* @param mixed $comparison
|
||||
*
|
||||
* @return int Return Values:<br>
|
||||
* < 0 if the object is less than comparison<br>
|
||||
* > 0 if the object is greater than comparison<br>
|
||||
* 0 if they are equal.
|
||||
*/
|
||||
public function compareTo(mixed $comparison): int;
|
||||
}
|
||||
39
vendor/phootwork/lang/ComparableComparator.php
vendored
Normal file
39
vendor/phootwork/lang/ComparableComparator.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class ComparableComparator
|
||||
*
|
||||
* Comparator for objects implementing phootwork\lang\Comparable interface.
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
*/
|
||||
class ComparableComparator implements Comparator {
|
||||
/**
|
||||
* @param mixed $a
|
||||
* @param mixed $b
|
||||
*
|
||||
* @throws InvalidArgumentException If the objects don't implement phootwork\lang\Comparable interface.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function compare(mixed $a, mixed $b): int {
|
||||
if (! $a instanceof Comparable) {
|
||||
throw new InvalidArgumentException(
|
||||
"ComparableComparator can compare only objects implementing phootwork\lang\Comparable interface"
|
||||
);
|
||||
}
|
||||
|
||||
return $a->compareTo($b);
|
||||
}
|
||||
}
|
||||
26
vendor/phootwork/lang/Comparator.php
vendored
Normal file
26
vendor/phootwork/lang/Comparator.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
interface Comparator {
|
||||
/**
|
||||
* Compares two objects
|
||||
*
|
||||
* @param mixed $a
|
||||
* @param mixed $b
|
||||
*
|
||||
* @return int
|
||||
* Return Values:
|
||||
* < 0 if the $a is less than $b
|
||||
* > 0 if the $a is greater than $b
|
||||
* 0 if they are equal.
|
||||
*/
|
||||
public function compare(mixed $a, mixed $b): int;
|
||||
}
|
||||
22
vendor/phootwork/lang/LICENSE
vendored
Normal file
22
vendor/phootwork/lang/LICENSE
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 - 2019 Thomas Gossmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
60
vendor/phootwork/lang/README.md
vendored
Normal file
60
vendor/phootwork/lang/README.md
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
# phootwork/lang
|
||||
|
||||

|
||||
[](https://scrutinizer-ci.com/g/phootwork/phootwork/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/phootwork/phootwork/?branch=master)
|
||||
[](https://packagist.org/packages/phootwork/lang)
|
||||
[](https://packagist.org/packages/phootwork/lang)
|
||||
[](https://packagist.org/packages/phootwork/lang)
|
||||
|
||||
Missing PHP language constructs
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide common but missing php classes
|
||||
- Objects for native php constructs
|
||||
- Consistent API
|
||||
- Inspired by `java.lang`, `java.util`, `String.prototype`, `Array.prototype` and [`Stringy`](https://github.com/danielstjules/Stringy)
|
||||
|
||||
## Installation
|
||||
|
||||
Installation via composer:
|
||||
|
||||
```
|
||||
composer require phootwork/lang
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
[https://phootwork.github.io/lang](https://phootwork.github.io/lang)
|
||||
|
||||
## Running tests
|
||||
|
||||
This package is a part of the Phootwork library. In order to run the test suite, you have to download the full library.
|
||||
|
||||
```
|
||||
git clone https://github.com/phootwork/phootwork
|
||||
```
|
||||
Then install the dependencies via composer:
|
||||
|
||||
```
|
||||
composer install
|
||||
```
|
||||
Now, run the *lang* test suite:
|
||||
|
||||
```
|
||||
vendor/bin/phpunit --testsuite lang
|
||||
```
|
||||
If you want to run the whole library tests, simply run:
|
||||
|
||||
```
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
|
||||
## Contact
|
||||
|
||||
Report issues at the github [Issue Tracker](https://github.com/phootwork/phootwork/issues).
|
||||
|
||||
## Changelog
|
||||
|
||||
Refer to [Releases](https://github.com/phootwork/phootwork/releases)
|
||||
19
vendor/phootwork/lang/StringComparator.php
vendored
Normal file
19
vendor/phootwork/lang/StringComparator.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
/**
|
||||
* String comparison
|
||||
*/
|
||||
class StringComparator implements Comparator {
|
||||
public function compare(mixed $a, mixed $b): int {
|
||||
return strcmp((string) $a, (string) $b);
|
||||
}
|
||||
}
|
||||
508
vendor/phootwork/lang/Text.php
vendored
Normal file
508
vendor/phootwork/lang/Text.php
vendored
Normal file
@ -0,0 +1,508 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang;
|
||||
|
||||
use phootwork\lang\parts\ArrayConversionsPart;
|
||||
use phootwork\lang\parts\CheckerPart;
|
||||
use phootwork\lang\parts\ComparisonPart;
|
||||
use phootwork\lang\parts\InternalPart;
|
||||
use phootwork\lang\parts\SearchPart;
|
||||
use phootwork\lang\parts\TransformationsPart;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Object representation of an immutable String
|
||||
*
|
||||
* @author gossi
|
||||
*/
|
||||
class Text implements Comparable, Stringable {
|
||||
use ArrayConversionsPart;
|
||||
use CheckerPart;
|
||||
use ComparisonPart;
|
||||
use SearchPart;
|
||||
use InternalPart;
|
||||
use TransformationsPart;
|
||||
|
||||
/** @var string */
|
||||
private string $string;
|
||||
|
||||
/** @var string */
|
||||
private string $encoding;
|
||||
|
||||
/**
|
||||
* Initializes a String object ad assigns both string and encoding properties
|
||||
* the supplied values. $string is cast to a string prior to assignment, and if
|
||||
* $encoding is not specified, it defaults to mb_internal_encoding(). Throws
|
||||
* an InvalidArgumentException if the first argument is an array or object
|
||||
* without a __toString method.
|
||||
*
|
||||
* @param string|Stringable $string Value to modify, after being cast to string
|
||||
* @param string|null $encoding The character encoding
|
||||
*
|
||||
* @psalm-suppress PossiblyInvalidPropertyAssignmentValue mb_internal_encoding always return string when called as getter
|
||||
*/
|
||||
public function __construct(string|Stringable $string = '', ?string $encoding = null) {
|
||||
$this->string = (string) $string;
|
||||
$this->encoding = $encoding ?? mb_internal_encoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Static initializing a String object.
|
||||
*
|
||||
* @param string|Stringable $string
|
||||
* @param string|null $encoding
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @see Text::__construct()
|
||||
*
|
||||
* @psalm-suppress UnsafeInstantiation
|
||||
*/
|
||||
public static function create(string|Stringable $string, ?string $encoding = null): static {
|
||||
return new static($string, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the used encoding
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEncoding(): string {
|
||||
return $this->encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string length
|
||||
*
|
||||
* <code>
|
||||
* $str = new Text('Hello World!');<br>
|
||||
* $str->length(); // 12
|
||||
*
|
||||
* $str = new Text('いちりんしゃ');<br>
|
||||
* $str->length(); // 6
|
||||
* </code>
|
||||
*
|
||||
* @return int Returns the length
|
||||
*/
|
||||
public function length(): int {
|
||||
return mb_strlen($this->string, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends <code>$string</code> and returns as a new <code>Text</code>
|
||||
*
|
||||
* @param string|Stringable $string
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function append(string|Stringable $string): self {
|
||||
return new self($this->string . $string, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends <code>$string</code> and returns as a new <code>Text</code>
|
||||
*
|
||||
* @param string|Stringable $string $string
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function prepend(string|Stringable $string): self {
|
||||
return new self($string . $this->string, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a substring at the given index
|
||||
*
|
||||
* <code>
|
||||
* $str = new Text('Hello World!');<br>
|
||||
* $str->insert('to this ', 5); // Hello to this World!
|
||||
* </code>
|
||||
*
|
||||
* @param string|Stringable $substring
|
||||
* @param int $index
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function insert(string|Stringable $substring, int $index): self {
|
||||
if ($index <= 0) {
|
||||
return $this->prepend($substring);
|
||||
}
|
||||
|
||||
if ($index > $this->length()) {
|
||||
return $this->append($substring);
|
||||
}
|
||||
|
||||
$start = mb_substr($this->string, 0, $index, $this->encoding);
|
||||
$end = mb_substr($this->string, $index, $this->length(), $this->encoding);
|
||||
|
||||
return new self($start . $substring . $end);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// SLICING AND SUBSTRING
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Slices a piece of the string from a given offset with a specified length.
|
||||
* If no length is given, the String is sliced to its maximum length.
|
||||
*
|
||||
* @see #substring
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function slice(int $offset, ?int $length = null): self {
|
||||
$offset = $this->prepareOffset($offset);
|
||||
$length = $this->prepareLength($offset, $length);
|
||||
|
||||
return new self(mb_substr($this->string, $offset, $length, $this->encoding), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Slices a piece of the string from a given start to an end.
|
||||
* If no length is given, the String is sliced to its maximum length.
|
||||
*
|
||||
* @see #slice
|
||||
*
|
||||
* @param int $start
|
||||
* @param int|null $end
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function substring(int $start, ?int $end = null): self {
|
||||
$length = $this->length();
|
||||
|
||||
if (null === $end) {
|
||||
$end = $length;
|
||||
}
|
||||
|
||||
if ($end < 0) {
|
||||
$end = $length + $end;
|
||||
}
|
||||
|
||||
$end = min($end, $length);
|
||||
$start = min($start, $end);
|
||||
$end = max($start, $end);
|
||||
$end = $end - $start;
|
||||
|
||||
return new self(mb_substr($this->string, $start, $end, $this->encoding), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of substring occurrences.
|
||||
*
|
||||
* @param string|Stringable $substring The substring to count the occurrencies
|
||||
* @param bool $caseSensitive Force case-sensitivity
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countSubstring(string|Stringable $substring, bool $caseSensitive = true): int {
|
||||
if (empty($substring)) {
|
||||
throw new \InvalidArgumentException('$substring cannot be empty');
|
||||
}
|
||||
|
||||
if ($caseSensitive) {
|
||||
return mb_substr_count($this->string, (string) $substring, $this->encoding);
|
||||
}
|
||||
$str = mb_strtoupper($this->string, $this->encoding);
|
||||
$substring = mb_strtoupper((string) $substring, $this->encoding);
|
||||
|
||||
return mb_substr_count($str, $substring, $this->encoding);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// REPLACING
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Replace all occurrences of the search string with the replacement string
|
||||
*
|
||||
* @see #supplant
|
||||
*
|
||||
* @param Arrayable|Stringable|array|string $search
|
||||
* The value being searched for, otherwise known as the needle. An array may be used
|
||||
* to designate multiple needles.
|
||||
* @param Arrayable|Stringable[]|array|string $replace
|
||||
* The replacement value that replaces found search values. An array may be used to
|
||||
* designate multiple replacements.
|
||||
*
|
||||
* @return Text
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion
|
||||
*/
|
||||
public function replace(Arrayable|Stringable|array|string $search, Arrayable|Stringable|array|string $replace): self {
|
||||
$search = $search instanceof Stringable ? (string) $search :
|
||||
($search instanceof Arrayable ? $search->toArray() : $search);
|
||||
$replace = $replace instanceof Stringable ? (string) $replace :
|
||||
($replace instanceof Arrayable ? $replace->toArray() : $replace);
|
||||
|
||||
return new self(str_replace($search, $replace, $this->string), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all occurrences of given replacement map. Keys will be replaced with its values.
|
||||
*
|
||||
* @param string[] $map the replacements. Keys will be replaced with its value.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function supplant(array $map): self {
|
||||
return new self(str_replace(array_keys($map), array_values($map), $this->string), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace text within a portion of a string.
|
||||
*
|
||||
* @param string|Stringable $replacement
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function splice(string|Stringable $replacement, int $offset, ?int $length = null): self {
|
||||
$offset = $this->prepareOffset($offset);
|
||||
$length = $this->prepareLength($offset, $length);
|
||||
|
||||
$start = $this->substring(0, $offset);
|
||||
$end = $this->substring($offset + $length);
|
||||
|
||||
return new self($start . $replacement . $end);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// STRING OPERATIONS
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* Strip whitespace (or other characters) from the beginning and end of the string
|
||||
*
|
||||
* @param string|Stringable $characters
|
||||
* Optionally, the stripped characters can also be specified using the mask parameter.
|
||||
* Simply list all characters that you want to be stripped. With .. you can specify a
|
||||
* range of characters.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function trim(string|Stringable $characters = " \t\n\r\v\0"): self {
|
||||
return new self(trim($this->string, (string) $characters), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip whitespace (or other characters) from the beginning of the string
|
||||
*
|
||||
* @param string|Stringable $characters
|
||||
* Optionally, the stripped characters can also be specified using the mask parameter.
|
||||
* Simply list all characters that you want to be stripped. With .. you can specify a
|
||||
* range of characters.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function trimStart(string|Stringable $characters = " \t\n\r\v\0"): self {
|
||||
return new self(ltrim($this->string, (string) $characters), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip whitespace (or other characters) from the end of the string
|
||||
*
|
||||
* @param string|Stringable $characters
|
||||
* Optionally, the stripped characters can also be specified using the mask parameter.
|
||||
* Simply list all characters that you want to be stripped. With .. you can specify a
|
||||
* range of characters.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function trimEnd(string|Stringable $characters = " \t\n\r\v\0"): self {
|
||||
return new self(rtrim($this->string, (string) $characters), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds padding to the start and end
|
||||
*
|
||||
* @param int $length
|
||||
* @param string|Stringable $padding
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function pad(int $length, string|Stringable $padding = ' '): self {
|
||||
$len = $length - $this->length();
|
||||
|
||||
return $this->applyPadding(floor($len / 2), ceil($len / 2), $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds padding to the start
|
||||
*
|
||||
* @param int $length
|
||||
* @param string|Stringable $padding
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function padStart(int $length, string|Stringable $padding = ' ') {
|
||||
return $this->applyPadding($length - $this->length(), 0, $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds padding to the end
|
||||
*
|
||||
* @param int $length
|
||||
* @param string|Stringable $padding
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function padEnd(int $length, string|Stringable $padding = ' '): self {
|
||||
return $this->applyPadding(0, $length - $this->length(), $padding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified amount of left and right padding to the given string.
|
||||
* The default character used is a space.
|
||||
*
|
||||
* @see https://github.com/danielstjules/Stringy/blob/master/src/Stringy.php
|
||||
*
|
||||
* @param int|float $left Length of left padding
|
||||
* @param int|float $right Length of right padding
|
||||
* @param string|Stringable $padStr String used to pad
|
||||
*
|
||||
* @return Text the padded string
|
||||
*/
|
||||
protected function applyPadding(int|float $left = 0, int|float $right = 0, string|Stringable $padStr = ' '): self {
|
||||
$length = mb_strlen((string) $padStr, $this->encoding);
|
||||
$strLength = $this->length();
|
||||
$paddedLength = $strLength + $left + $right;
|
||||
if (!$length || $paddedLength <= $strLength) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$leftPadding = mb_substr(str_repeat((string) $padStr, (int) ceil($left / $length)), 0, (int) $left, $this->encoding);
|
||||
$rightPadding = mb_substr(str_repeat((string) $padStr, (int) ceil($right / $length)), 0, (int) $right, $this->encoding);
|
||||
|
||||
return new self($leftPadding . $this->string . $rightPadding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a given substring at the start of the string
|
||||
*
|
||||
* @param string $substring
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function ensureStart(string $substring): self {
|
||||
if (!$this->startsWith($substring)) {
|
||||
return $this->prepend($substring);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a given substring at the end of the string
|
||||
*
|
||||
* @param string $substring
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function ensureEnd(string $substring): self {
|
||||
if (!$this->endsWith($substring)) {
|
||||
return $this->append($substring);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the string wrapped at a given number of characters
|
||||
*
|
||||
* @param int $width The number of characters at which the string will be wrapped.
|
||||
* @param string $break The line is broken using the optional break parameter.
|
||||
* @param bool $cut
|
||||
* If the cut is set to TRUE, the string is always wrapped at or before the specified
|
||||
* width. So if you have a word that is larger than the given width, it is broken apart.
|
||||
*
|
||||
* @return Text Returns the string wrapped at the specified length.
|
||||
*/
|
||||
public function wrapWords(int $width = 75, string $break = "\n", bool $cut = false): self {
|
||||
return new self(wordwrap($this->string, $width, $break, $cut), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the string $times times. If $times is 0, it returns ''.
|
||||
*
|
||||
* @param int $multiplier
|
||||
*
|
||||
* @throws \InvalidArgumentException If $times is negative.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function repeat(int $multiplier): self {
|
||||
return new self(str_repeat($this->string, $multiplier), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the character order
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function reverse(): self {
|
||||
return new self(strrev($this->string), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the string with a substring and ensures it doesn't exceed the given length
|
||||
*
|
||||
* @param int $length
|
||||
* @param string $substring
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function truncate(int $length, string $substring = ''): self {
|
||||
if ($this->length() <= $length) {
|
||||
return new self($this->string, $this->encoding);
|
||||
}
|
||||
|
||||
$substrLen = mb_strlen($substring, $this->encoding);
|
||||
|
||||
if ($this->length() + $substrLen > $length) {
|
||||
$length -= $substrLen;
|
||||
}
|
||||
|
||||
return $this->substring(0, $length)->append($substring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the native string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toString(): string {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
protected function getString(): string {
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// MAGIC HAPPENS HERE
|
||||
//
|
||||
//
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->string;
|
||||
}
|
||||
}
|
||||
31
vendor/phootwork/lang/composer.json
vendored
Normal file
31
vendor/phootwork/lang/composer.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name" : "phootwork/lang",
|
||||
"type" : "library",
|
||||
"description" : "Missing PHP language constructs",
|
||||
"authors" : [{
|
||||
"name" : "Thomas Gossmann",
|
||||
"homepage" : "http://gos.si"
|
||||
}
|
||||
],
|
||||
"license" : "MIT",
|
||||
"keywords" : [
|
||||
"array",
|
||||
"string",
|
||||
"comparison",
|
||||
"comparator"
|
||||
],
|
||||
"support" : {
|
||||
"issues" : "https://github.com/phootwork/phootwork/issues"
|
||||
},
|
||||
"autoload" : {
|
||||
"psr-4" : {
|
||||
"phootwork\\lang\\" : ""
|
||||
}
|
||||
},
|
||||
"require" : {
|
||||
"php" : ">=8.0",
|
||||
"symfony/polyfill-mbstring" : "^1.12",
|
||||
"symfony/polyfill-php81": "^1.22"
|
||||
},
|
||||
"homepage" : "https://phootwork.github.io/lang/"
|
||||
}
|
||||
327
vendor/phootwork/lang/inflector/Inflector.php
vendored
Normal file
327
vendor/phootwork/lang/inflector/Inflector.php
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\inflector;
|
||||
|
||||
/**
|
||||
* Standard replacement English pluralizer class. Based on the links below
|
||||
*
|
||||
* @link http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
|
||||
* @link http://blogs.msdn.com/dmitryr/archive/2007/01/11/simple-english-noun-pluralizer-in-c.aspx
|
||||
* @link http://api.cakephp.org/view_source/inflector/
|
||||
*
|
||||
* @author paul.hanssen
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
class Inflector implements InflectorInterface {
|
||||
protected array $plural = [
|
||||
'(ind|vert)ex' => '\1ices',
|
||||
'(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us' => '\1i',
|
||||
'(buffal|tomat)o' => '\1oes',
|
||||
|
||||
'x' => 'xes',
|
||||
'ch' => 'ches',
|
||||
'sh' => 'shes',
|
||||
'ss' => 'sses',
|
||||
|
||||
'ay' => 'ays',
|
||||
'ey' => 'eys',
|
||||
'iy' => 'iys',
|
||||
'oy' => 'oys',
|
||||
'uy' => 'uys',
|
||||
'y' => 'ies',
|
||||
|
||||
'ao' => 'aos',
|
||||
'eo' => 'eos',
|
||||
'io' => 'ios',
|
||||
'oo' => 'oos',
|
||||
'uo' => 'uos',
|
||||
'o' => 'os',
|
||||
|
||||
'us' => 'uses',
|
||||
|
||||
'cis' => 'ces',
|
||||
'sis' => 'ses',
|
||||
'xis' => 'xes',
|
||||
|
||||
'zoon' => 'zoa',
|
||||
|
||||
'itis' => 'itis',
|
||||
'ois' => 'ois',
|
||||
'pox' => 'pox',
|
||||
'ox' => 'oxes',
|
||||
|
||||
'foot' => 'feet',
|
||||
'goose' => 'geese',
|
||||
'tooth' => 'teeth',
|
||||
'quiz' => 'quizzes',
|
||||
'alias' => 'aliases',
|
||||
|
||||
'alf' => 'alves',
|
||||
'elf' => 'elves',
|
||||
'olf' => 'olves',
|
||||
'arf' => 'arves',
|
||||
'nife' => 'nives',
|
||||
'life' => 'lives'
|
||||
];
|
||||
|
||||
protected array $irregular = [
|
||||
'matrix' => 'matrices',
|
||||
'leaf' => 'leaves',
|
||||
'loaf' => 'loaves',
|
||||
'move' => 'moves',
|
||||
'foot' => 'feet',
|
||||
'goose' => 'geese',
|
||||
'genus' => 'genera',
|
||||
'sex' => 'sexes',
|
||||
'ox' => 'oxen',
|
||||
'child' => 'children',
|
||||
'man' => 'men',
|
||||
'tooth' => 'teeth',
|
||||
'person' => 'people',
|
||||
'wife' => 'wives',
|
||||
'mythos' => 'mythoi',
|
||||
'testis' => 'testes',
|
||||
'numen' => 'numina',
|
||||
'quiz' => 'quizzes',
|
||||
'alias' => 'aliases',
|
||||
];
|
||||
|
||||
protected array $uncountable = [
|
||||
'sheep',
|
||||
'fish',
|
||||
'deer',
|
||||
'series',
|
||||
'species',
|
||||
'money',
|
||||
'rice',
|
||||
'information',
|
||||
'equipment',
|
||||
'news',
|
||||
'people',
|
||||
];
|
||||
|
||||
protected array $singular;
|
||||
|
||||
/**
|
||||
* Array of words that could be ambiguously interpreted. Eg:
|
||||
* `isPlural` method can't recognize 'menus' as plural, because it considers 'menus' as the
|
||||
* singular of 'menuses'.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected array $ambiguous = [
|
||||
'menu' => 'menus'
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
// Create the $singular array
|
||||
$this->singular = array_flip($this->plural);
|
||||
$this->singular = array_slice($this->singular, 3);
|
||||
|
||||
$reg = [
|
||||
'(ind|vert)ices' => '\1ex',
|
||||
'(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)i' => '\1us',
|
||||
'(buffal|tomat)oes' => '\1o'
|
||||
];
|
||||
|
||||
$this->singular = array_merge($reg, $this->singular);
|
||||
|
||||
// We have an ambiguity: -xes is the plural form of -x or -xis. By now, we choose -x. Words with -xis suffix
|
||||
// should be added to the $ambiguous array.
|
||||
$this->singular['xes'] = 'x';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a plural name based on the passed in root.
|
||||
*
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
*
|
||||
* @throws \InvalidArgumentException If the parameter is not a string.
|
||||
*
|
||||
* @return string The plural form of $root (e.g. Authors).
|
||||
*/
|
||||
public function getPluralForm(string $root): string {
|
||||
$pluralForm = $root;
|
||||
|
||||
if (!in_array(strtolower($root), $this->uncountable)) {
|
||||
// This check must be run before `checkIrregularForm` call
|
||||
if (!$this->isAmbiguousPlural($root)) {
|
||||
if (null !== $replacement = $this->checkIrregularForm($root, $this->irregular)) {
|
||||
$pluralForm = $replacement;
|
||||
} elseif (null !== $replacement = $this->checkIrregularSuffix($root, $this->plural)) {
|
||||
$pluralForm = $replacement;
|
||||
} elseif (!$this->isPlural($root)) {
|
||||
// fallback to naive pluralization
|
||||
$pluralForm = $root . 's';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $pluralForm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a singular name based on the passed in root.
|
||||
*
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
*
|
||||
* @throws \InvalidArgumentException If the parameter is not a string.
|
||||
*
|
||||
* @return string The singular form of $root (e.g. Authors).
|
||||
*/
|
||||
public function getSingularForm(string $root): string {
|
||||
$singularForm = $root;
|
||||
|
||||
if (!in_array(strtolower($root), $this->uncountable)) {
|
||||
if (null !== $replacement = $this->checkIrregularForm($root, array_flip($this->irregular))) {
|
||||
$singularForm = $replacement;
|
||||
} elseif (null !== $replacement = $this->checkIrregularSuffix($root, $this->singular)) {
|
||||
$singularForm = $replacement;
|
||||
} elseif (!$this->isSingular($root)) {
|
||||
// fallback to naive singularization
|
||||
return substr($root, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return $singularForm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $root word is plural.
|
||||
*
|
||||
* @param string $root
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion `array_keys($this->singular)` is an array of strings
|
||||
*/
|
||||
public function isPlural(string $root): bool {
|
||||
if ('' === $root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array(strtolower($root), $this->uncountable) ||
|
||||
$this->isIrregular($this->irregular, $root) ||
|
||||
$this->isIrregular(array_keys($this->singular), $root) ||
|
||||
's' == $root[strlen($root) - 1]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $root word is singular.
|
||||
*
|
||||
* @param $root
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion `array_keys($this->plural)` is an array of strings
|
||||
*/
|
||||
public function isSingular(string $root): bool {
|
||||
if ('' === $root || in_array(strtolower($root), $this->uncountable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isAmbiguousPlural($root)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->isIrregular($this->irregular, $root) ||
|
||||
$this->isIrregular(array_keys($this->plural), $root) ||
|
||||
's' !== $root[strlen($root) - 1]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluralize/Singularize irregular forms.
|
||||
*
|
||||
* @param string $root The string to pluralize/singularize
|
||||
* @param array $irregular Array of irregular forms
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private function checkIrregularForm(string $root, array $irregular): ?string {
|
||||
/**
|
||||
* @var string $pattern
|
||||
* @var string $result
|
||||
*/
|
||||
foreach ($irregular as $pattern => $result) {
|
||||
$searchPattern = '/' . $pattern . '$/i';
|
||||
if ($root !== $replacement = preg_replace($searchPattern, $result, $root)) {
|
||||
// look at the first char and see if it's upper case
|
||||
// I know it won't handle more than one upper case char here (but I'm OK with that)
|
||||
if (preg_match('/^[A-Z]/', $root)) {
|
||||
$replacement = ucfirst($replacement);
|
||||
}
|
||||
|
||||
return $replacement;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $root
|
||||
* @param array $irregular Array of irregular suffixes
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private function checkIrregularSuffix(string $root, array $irregular): ?string {
|
||||
/**
|
||||
* @var string $pattern
|
||||
* @var string $result
|
||||
*/
|
||||
foreach ($irregular as $pattern => $result) {
|
||||
$searchPattern = '/' . $pattern . '$/i';
|
||||
if ($root !== $replacement = preg_replace($searchPattern, $result, $root)) {
|
||||
return $replacement;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $root
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isAmbiguousPlural(string $root): bool {
|
||||
foreach ($this->ambiguous as $pattern) {
|
||||
if (preg_match('/' . $pattern . '$/i', $root)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $irregular
|
||||
* @param string $root
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isIrregular(array $irregular, string $root): bool {
|
||||
foreach ($irregular as $pattern) {
|
||||
if (preg_match('/' . $pattern . '$/i', $root)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
54
vendor/phootwork/lang/inflector/InflectorInterface.php
vendored
Normal file
54
vendor/phootwork/lang/inflector/InflectorInterface.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\inflector;
|
||||
|
||||
/**
|
||||
* The generic interface to create a plural form of a name.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
* @author Cristiano Cinotti <cristianocinotti@gmail.com>
|
||||
*/
|
||||
interface InflectorInterface {
|
||||
/**
|
||||
* Generate a plural name based on the passed in root.
|
||||
*
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
*
|
||||
* @return string The plural form of $root.
|
||||
*/
|
||||
public function getPluralForm(string $root): string;
|
||||
|
||||
/**
|
||||
* Generate a singular name based on the passed in root.
|
||||
*
|
||||
* @param string $root The root that needs to be singularized (e.g. Authors)
|
||||
*
|
||||
* @return string The singular form of $root.
|
||||
*/
|
||||
public function getSingularForm(string $root): string;
|
||||
|
||||
/**
|
||||
* Check if $root word is plural.
|
||||
*
|
||||
* @param string $root
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPlural(string $root): bool;
|
||||
|
||||
/**
|
||||
* Check if $root word is singular.
|
||||
*
|
||||
* @param $root
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSingular(string $root): bool;
|
||||
}
|
||||
23
vendor/phootwork/lang/parts/AccessorsPart.php
vendored
Normal file
23
vendor/phootwork/lang/parts/AccessorsPart.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait AccessorsPart {
|
||||
/**
|
||||
* Returns the element at the given index (or null if the index isn't present)
|
||||
*
|
||||
* @param int|string $index
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(int|string $index): mixed {
|
||||
return $this->array[$index] ?? null;
|
||||
}
|
||||
}
|
||||
28
vendor/phootwork/lang/parts/AddPart.php
vendored
Normal file
28
vendor/phootwork/lang/parts/AddPart.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait AddPart {
|
||||
/**
|
||||
* Adds one or more elements to that array
|
||||
*
|
||||
* @param mixed ...$elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add(mixed ...$elements): self {
|
||||
/** @var mixed $element */
|
||||
foreach ($elements as $element) {
|
||||
$this->array[count($this->array)] = $element;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
103
vendor/phootwork/lang/parts/ArrayConversionsPart.php
vendored
Normal file
103
vendor/phootwork/lang/parts/ArrayConversionsPart.php
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phootwork\lang\ArrayObject;
|
||||
use phootwork\lang\Text;
|
||||
|
||||
/**
|
||||
* Text methods for array/ArrayObject conversions
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
trait ArrayConversionsPart {
|
||||
abstract protected function getString(): string;
|
||||
|
||||
/**
|
||||
* Splits the string by string
|
||||
*
|
||||
* @param string $delimiter The boundary string.
|
||||
* @param int $limit
|
||||
* If limit is set and positive, the returned array will contain a maximum of
|
||||
* limit elements with the last element containing the rest of string.
|
||||
*
|
||||
* If the limit parameter is negative, all components except the last
|
||||
* -limit are returned.
|
||||
*
|
||||
* If the limit parameter is zero, then this is treated as 1.
|
||||
*
|
||||
* @throws InvalidArgumentException If the delimiter is an empty string.
|
||||
*
|
||||
* @return ArrayObject
|
||||
* Returns an array of strings created by splitting the string parameter on boundaries
|
||||
* formed by the delimiter.
|
||||
*
|
||||
* If delimiter contains a value that is not contained in string and a negative limit is used,
|
||||
* then an empty array will be returned, otherwise an array containing string will be returned.
|
||||
*
|
||||
*/
|
||||
public function split(string $delimiter, int $limit = PHP_INT_MAX): ArrayObject {
|
||||
if ('' === $delimiter) {
|
||||
throw new InvalidArgumentException("The delimiter can't be an empty string");
|
||||
}
|
||||
|
||||
return new ArrayObject(explode($delimiter, $this->getString(), $limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Join array elements with a string
|
||||
*
|
||||
* @param array $pieces The array of strings to join.
|
||||
* @param string $glue Defaults to an empty string.
|
||||
* @param string|null $encoding the desired encoding
|
||||
*
|
||||
* @return Text
|
||||
* Returns a string containing a string representation of all the array elements in the
|
||||
* same order, with the glue string between each element.
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion
|
||||
*/
|
||||
public static function join(array $pieces, string $glue = '', ?string $encoding = null): Text {
|
||||
array_map(
|
||||
function (mixed $element): void {
|
||||
if (!($element === null || is_scalar($element) || $element instanceof \Stringable)) {
|
||||
throw new \TypeError('Can join elements only if scalar, null or \\Stringable');
|
||||
}
|
||||
},
|
||||
$pieces
|
||||
);
|
||||
|
||||
return new Text(implode($glue, $pieces), $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the string to an array
|
||||
*
|
||||
* @param int $splitLength Maximum length of the chunk.
|
||||
*
|
||||
* @throws InvalidArgumentException If splitLength is less than 1.
|
||||
*
|
||||
* @return ArrayObject
|
||||
* If the optional splitLength parameter is specified, the returned array will be
|
||||
* broken down into chunks with each being splitLength in length, otherwise each chunk
|
||||
* will be one character in length.
|
||||
* If the split_length length exceeds the length of string, the entire string is returned
|
||||
* as the first (and only) array element.
|
||||
*/
|
||||
public function chunk(int $splitLength = 1): ArrayObject {
|
||||
if (false === $array = str_split($this->getString(), $splitLength)) {
|
||||
throw new InvalidArgumentException('The chunk length has to be positive');
|
||||
}
|
||||
|
||||
return new ArrayObject($array);
|
||||
}
|
||||
}
|
||||
133
vendor/phootwork/lang/parts/CheckerPart.php
vendored
Normal file
133
vendor/phootwork/lang/parts/CheckerPart.php
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use phootwork\lang\inflector\Inflector;
|
||||
use phootwork\lang\inflector\InflectorInterface;
|
||||
|
||||
trait CheckerPart {
|
||||
abstract protected function getString(): string;
|
||||
|
||||
/**
|
||||
* Checks if the string is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool {
|
||||
return empty($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only alphanumeric characters.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAlphanumeric(): bool {
|
||||
return ctype_alnum($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only alphanumeric characters.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAlphabetic(): bool {
|
||||
return ctype_alpha($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only numeric characters.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNumeric(): bool {
|
||||
return ctype_digit($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only characters which are not whitespace or an alphanumeric.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPunctuation(): bool {
|
||||
return ctype_punct($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only space characters.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSpace(): bool {
|
||||
return ctype_space($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only lower case characters.
|
||||
*
|
||||
* Spaces are considered non-lowercase characters, so lowercase strings with multiple words, separated by spaces,
|
||||
* return false. E.g.:
|
||||
*
|
||||
* <code>
|
||||
* $text = new Text('lowercase multi words string');<br>
|
||||
* var_dump($text->isLowercase()); // false
|
||||
* </code>
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLowerCase(): bool {
|
||||
return ctype_lower($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains only upper case characters.
|
||||
*
|
||||
* Spaces are considered non-uppercase characters, so uppercase strings with multiple words, separated by spaces,
|
||||
* return false. E.g.:
|
||||
*
|
||||
* <code>
|
||||
* $text = new Text('UPPERCASE MULTI WORDS STRING'); <br>
|
||||
* var_dump($text->isUppercase()); // false
|
||||
* </code>
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUpperCase(): bool {
|
||||
return ctype_upper($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is singular form.
|
||||
*
|
||||
* @param InflectorInterface|null $pluralizer
|
||||
* A custom pluralizer. Default is the Inflector
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSingular(?InflectorInterface $pluralizer = null): bool {
|
||||
$pluralizer = $pluralizer ?? new Inflector();
|
||||
|
||||
return $pluralizer->isSingular($this->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is plural form.
|
||||
*
|
||||
* @param InflectorInterface|null $pluralizer
|
||||
* A custom pluralizer. Default is the Inflector
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPlural(?InflectorInterface $pluralizer = null): bool {
|
||||
$pluralizer = $pluralizer ?? new Inflector();
|
||||
|
||||
return $pluralizer->isPlural($this->getString());
|
||||
}
|
||||
}
|
||||
93
vendor/phootwork/lang/parts/ComparisonPart.php
vendored
Normal file
93
vendor/phootwork/lang/parts/ComparisonPart.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use phootwork\lang\Text;
|
||||
|
||||
/**
|
||||
* Text methods to perform string and Text object comparison
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
trait ComparisonPart {
|
||||
abstract protected function getString(): string;
|
||||
|
||||
/**
|
||||
* Compares this string to another
|
||||
*
|
||||
* @param mixed $comparison
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @see \phootwork\lang\Comparable::compareTo()
|
||||
*/
|
||||
public function compareTo(mixed $comparison): int {
|
||||
if (is_string($comparison) || $comparison instanceof Text) {
|
||||
return $this->compare($comparison);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('`compareTo` method can accept only strings or Text objects.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this string to another string, ignoring the case
|
||||
*
|
||||
* @param string|Text $compare
|
||||
*
|
||||
* @return int Return Values:<br>
|
||||
* < 0 if the object is less than comparison<br>
|
||||
* > 0 if the object is greater than comparison<br>
|
||||
* 0 if they are equal.
|
||||
*/
|
||||
public function compareCaseInsensitive(string|Text $compare): int {
|
||||
return $this->compare($compare, 'strcasecmp');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this string to another
|
||||
*
|
||||
* @param string|Text $compare string to compare to
|
||||
* @param callable|null $callback
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @psalm-suppress MixedInferredReturnType
|
||||
*/
|
||||
public function compare(string|Text $compare, ?callable $callback = null): int {
|
||||
if ($callback === null) {
|
||||
$callback = 'strcmp';
|
||||
}
|
||||
|
||||
return $callback($this->getString(), (string) $compare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string and the given object are equal
|
||||
*
|
||||
* @param string|Text $string
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(string|Text $string): bool {
|
||||
return $this->compareTo($string) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string and the given object are equal ignoring the case
|
||||
*
|
||||
* @param string|Text $string
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equalsIgnoreCase(string|Text $string): bool {
|
||||
return $this->compareCaseInsensitive($string) === 0;
|
||||
}
|
||||
}
|
||||
21
vendor/phootwork/lang/parts/EachPart.php
vendored
Normal file
21
vendor/phootwork/lang/parts/EachPart.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait EachPart {
|
||||
/**
|
||||
* Iterates the array and calls the callback function with the current item as parameter
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function each(callable $callback): void {
|
||||
array_map($callback, $this->array);
|
||||
}
|
||||
}
|
||||
78
vendor/phootwork/lang/parts/IndexFindersPart.php
vendored
Normal file
78
vendor/phootwork/lang/parts/IndexFindersPart.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait IndexFindersPart {
|
||||
abstract public function find(mixed ...$arguments);
|
||||
|
||||
abstract public function findLast(mixed ...$arguments);
|
||||
|
||||
/**
|
||||
* Returns the index of the given element or null if the element can't be found
|
||||
*
|
||||
* @param mixed $element
|
||||
*
|
||||
* @return int|string|null the index for the given element
|
||||
*/
|
||||
public function indexOf(mixed $element): int|string|null {
|
||||
$out = array_search($element, $this->array, true);
|
||||
|
||||
return $out === false ? null : $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the index for the last element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return int|string|null the index or null if it hasn't been found
|
||||
*/
|
||||
public function findLastIndex(mixed ...$arguments): int|string|null {
|
||||
/** @var mixed $index */
|
||||
$index = count($arguments) === 1 ?
|
||||
$this->findLast($arguments[0]) : $this->findLast($arguments[0], $arguments[1]);
|
||||
|
||||
return $this->indexOf($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the array with a given callback and returns the index for the first element if found.
|
||||
*
|
||||
* The callback function takes one or two parameters:
|
||||
*
|
||||
* function ($element [, $query]) {}
|
||||
*
|
||||
* The callback must return a boolean
|
||||
* When it's passed, $query must be the first argument:
|
||||
*
|
||||
* - find($query, callback)
|
||||
* - find(callback)
|
||||
*
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return int|string|null the index or null if it hasn't been found
|
||||
*/
|
||||
public function findIndex(mixed ...$arguments): int|string|null {
|
||||
/** @var mixed $index */
|
||||
$index = count($arguments) === 1 ? $this->find($arguments[0]) : $this->find($arguments[0], $arguments[1]);
|
||||
|
||||
return $this->indexOf($index);
|
||||
}
|
||||
}
|
||||
33
vendor/phootwork/lang/parts/InsertPart.php
vendored
Normal file
33
vendor/phootwork/lang/parts/InsertPart.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait InsertPart {
|
||||
abstract public function add(mixed ...$elements);
|
||||
|
||||
/**
|
||||
* Insert one element at the given index
|
||||
*
|
||||
* @param mixed $element
|
||||
* @param int|null|string $index
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function insert(mixed $element, int|string|null $index): self {
|
||||
if (null === $index) {
|
||||
return $this->add($element);
|
||||
}
|
||||
|
||||
is_int($index) ? array_splice($this->array, $index, 0, [$element])
|
||||
: $this->array[$index] = $element;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
67
vendor/phootwork/lang/parts/InternalPart.php
vendored
Normal file
67
vendor/phootwork/lang/parts/InternalPart.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Internal Text methods
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
trait InternalPart {
|
||||
abstract public function length(): int;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param int $offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function prepareOffset(int $offset): int {
|
||||
$len = $this->length();
|
||||
if ($offset < -$len || $offset > $len) {
|
||||
throw new InvalidArgumentException("Offset must be in range [-$len, $len]");
|
||||
}
|
||||
|
||||
if ($offset < 0) {
|
||||
$offset += $len;
|
||||
}
|
||||
|
||||
return $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int|null $length
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
protected function prepareLength(int $offset, ?int $length): int {
|
||||
$length = (null === $length) ? ($this->length() - $offset) : (
|
||||
($length < 0) ? ($length + $this->length() - $offset) : $length
|
||||
);
|
||||
|
||||
if ($length < 0) {
|
||||
throw new InvalidArgumentException('Length too small');
|
||||
}
|
||||
|
||||
if ($offset + $length > $this->length()) {
|
||||
throw new InvalidArgumentException('Length too large');
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
}
|
||||
21
vendor/phootwork/lang/parts/PopPart.php
vendored
Normal file
21
vendor/phootwork/lang/parts/PopPart.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait PopPart {
|
||||
/**
|
||||
* Pop the element off the end of array
|
||||
*
|
||||
* @return mixed the popped element
|
||||
*/
|
||||
public function pop(): mixed {
|
||||
return array_pop($this->array);
|
||||
}
|
||||
}
|
||||
28
vendor/phootwork/lang/parts/ReducePart.php
vendored
Normal file
28
vendor/phootwork/lang/parts/ReducePart.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait ReducePart {
|
||||
/**
|
||||
* Iterative reduction of this array or collection with the help of a callback function. The callback
|
||||
* function takes two parameters, the first is the carry, the second the current item, with this
|
||||
* signature: mixed callback(mixed $carry, mixed $item)
|
||||
*
|
||||
* @param callable $callback the callback function
|
||||
* @param mixed $fallback the default value, that will be returned when the list is empty
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-suppress MixedArgumentTypeCoercion $callback is a callback
|
||||
*/
|
||||
public function reduce(callable $callback, mixed $fallback = null): mixed {
|
||||
return array_reduce($this->array, $callback, $fallback);
|
||||
}
|
||||
}
|
||||
43
vendor/phootwork/lang/parts/RemovePart.php
vendored
Normal file
43
vendor/phootwork/lang/parts/RemovePart.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait RemovePart {
|
||||
/**
|
||||
* Removes one or more elements from the array
|
||||
*
|
||||
* @param mixed ...$elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function remove(mixed ...$elements): self {
|
||||
/** @var mixed $element */
|
||||
foreach ($elements as $element) {
|
||||
$index = array_search($element, $this->array, true);
|
||||
if ($index !== false) {
|
||||
unset($this->array[$index]);
|
||||
$this->reorderList();
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function reorderList(): void {
|
||||
if (count(array_filter(array_keys($this->array), 'is_string')) > 0) {
|
||||
//it's an associative array: do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (!array_is_list($this->array)) {
|
||||
$this->array = array_values($this->array);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
vendor/phootwork/lang/parts/ReversePart.php
vendored
Normal file
23
vendor/phootwork/lang/parts/ReversePart.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
trait ReversePart {
|
||||
/**
|
||||
* Reverses the order of all elements
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reverse(): self {
|
||||
$this->array = array_reverse($this->array);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
166
vendor/phootwork/lang/parts/SearchPart.php
vendored
Normal file
166
vendor/phootwork/lang/parts/SearchPart.php
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use phootwork\lang\ArrayObject;
|
||||
use phootwork\lang\Text;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Text searching methods
|
||||
*
|
||||
* @author ThomasGossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
trait SearchPart {
|
||||
abstract protected function getString(): string;
|
||||
|
||||
abstract public function length(): int;
|
||||
|
||||
/**
|
||||
* Returns the character at the given zero-related index
|
||||
*
|
||||
* <code>
|
||||
* $str = new Text('Hello World!');<br>
|
||||
* $str->at(6); // W
|
||||
*
|
||||
* $str = new Text('いちりんしゃ');<br>
|
||||
* $str->at(4) // し
|
||||
* </code>
|
||||
*
|
||||
* @param int $index zero-related index
|
||||
*
|
||||
* @return string the found character
|
||||
*/
|
||||
public function at(int $index): string {
|
||||
return mb_substr($this->getString(), $index, 1, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ArrayObject consisting of the characters in the string.
|
||||
*
|
||||
* @return ArrayObject An ArrayObject of all chars
|
||||
*/
|
||||
public function chars(): ArrayObject {
|
||||
return new ArrayObject(mb_str_split($this->getString(), 1, $this->encoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of a given string, starting at the optional zero-related offset
|
||||
*
|
||||
* @param string|Stringable $string
|
||||
* @param int $offset zero-related offset
|
||||
*
|
||||
* @return int|null int for the index or null if the given string doesn't occur
|
||||
*/
|
||||
public function indexOf(string|Stringable $string, int $offset = 0): ?int {
|
||||
$output = mb_strpos($this->getString(), (string) $string, $offset, $this->encoding);
|
||||
|
||||
return false === $output ? null : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last index of a given string, starting at the optional offset
|
||||
*
|
||||
* @param string|Stringable $string $string
|
||||
* @param int|null $offset
|
||||
*
|
||||
* @return int|null int for the index or null if the given string doesn't occur
|
||||
*/
|
||||
public function lastIndexOf(string|Stringable $string, ?int $offset = null): ?int {
|
||||
if (null === $offset) {
|
||||
$offset = $this->length();
|
||||
}
|
||||
|
||||
// Converts $offset to a negative offset as strrpos has a different
|
||||
// behavior for positive offsets.
|
||||
$output = mb_strrpos($this->getString(), (string) $string, $offset - $this->length(), $this->encoding);
|
||||
|
||||
return false === $output ? null : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string starts with the given string. Case sensitive!
|
||||
*
|
||||
* @param string|Stringable $substring The substring to look for
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see Text::startsWithIgnoreCase()
|
||||
*
|
||||
*/
|
||||
public function startsWith(string|Stringable $substring): bool {
|
||||
return str_starts_with($this->getString(), (string) $substring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string starts with the given string. Ignores case.
|
||||
*
|
||||
* @param string|Stringable $substring The substring to look for
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see Text::startsWith()
|
||||
*
|
||||
*/
|
||||
public function startsWithIgnoreCase(string|Stringable $substring): bool {
|
||||
return str_starts_with($this->toUpperCase()->getString(), mb_strtoupper((string) $substring, $this->encoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string ends with the given string. Case sensitive!
|
||||
*
|
||||
* @param string|Stringable $substring The substring to look for
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see Text::endsWithIgnoreCase()
|
||||
*
|
||||
*/
|
||||
public function endsWith(string|Stringable $substring): bool {
|
||||
return str_ends_with($this->getString(), (string) $substring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string ends with the given string. Ingores case.
|
||||
*
|
||||
* @param string|Stringable $substring The substring to look for
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see Text::endsWith()
|
||||
*
|
||||
*/
|
||||
public function endsWithIgnoreCase(string|Stringable $substring): bool {
|
||||
return str_ends_with($this->toUpperCase()->getString(), mb_strtoupper((string) $substring, $this->encoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given string occurs
|
||||
*
|
||||
* @param string|Stringable $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(Stringable|string $text): bool {
|
||||
return str_contains($this->getString(), (string) $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a regular expression matching with the given regexp
|
||||
*
|
||||
* @param string $regexp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function match(string $regexp): bool {
|
||||
return (bool) preg_match($regexp, $this->getString());
|
||||
}
|
||||
}
|
||||
40
vendor/phootwork/lang/parts/SortAssocPart.php
vendored
Normal file
40
vendor/phootwork/lang/parts/SortAssocPart.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use phootwork\lang\Comparator;
|
||||
|
||||
trait SortAssocPart {
|
||||
/**
|
||||
* Sorts the array and persisting key-value pairs
|
||||
*
|
||||
* @param Comparator|callable|null $cmp
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sortAssoc(Comparator|callable|null $cmp = null): self {
|
||||
$this->doSort($this->array, 'uasort', 'asort', $cmp);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the array by keys
|
||||
*
|
||||
* @param Comparator|callable|null $cmp
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sortKeys(Comparator|callable|null $cmp = null): self {
|
||||
$this->doSort($this->array, 'uksort', 'ksort', $cmp);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
281
vendor/phootwork/lang/parts/TransformationsPart.php
vendored
Normal file
281
vendor/phootwork/lang/parts/TransformationsPart.php
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the Phootwork package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
* @copyright Thomas Gossmann
|
||||
*/
|
||||
namespace phootwork\lang\parts;
|
||||
|
||||
use phootwork\lang\Arrayable;
|
||||
use phootwork\lang\ArrayObject;
|
||||
use phootwork\lang\inflector\Inflector;
|
||||
use phootwork\lang\inflector\InflectorInterface;
|
||||
use phootwork\lang\Text;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Text transformation methods
|
||||
*
|
||||
* @author Thomas Gossmann
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
trait TransformationsPart {
|
||||
abstract protected function getString(): string;
|
||||
|
||||
/**
|
||||
* Slices a piece of the string from a given start to an end.
|
||||
* If no length is given, the String is sliced to its maximum length.
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
abstract public function substring(int $start, ?int $end = null): Text;
|
||||
|
||||
/**
|
||||
* Splits the string by string
|
||||
*
|
||||
* @param string $delimiter
|
||||
* @param int $limit
|
||||
*
|
||||
* @return ArrayObject
|
||||
*/
|
||||
abstract public function split(string $delimiter, int $limit = PHP_INT_MAX): ArrayObject;
|
||||
|
||||
/**
|
||||
* Strip whitespace (or other characters) from the beginning and end of the string
|
||||
*
|
||||
* @param string $characters
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
abstract public function trim(string $characters): Text;
|
||||
|
||||
/**
|
||||
* @param string|Stringable $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function contains(Stringable|string $text): bool;
|
||||
|
||||
/**
|
||||
* Replace all occurrences of the search string with the replacement string
|
||||
*
|
||||
* @param Arrayable|Stringable|array|string $search
|
||||
* The value being searched for, otherwise known as the needle. An array may be used
|
||||
* to designate multiple needles.
|
||||
* @param Arrayable|Stringable|array|string $replace
|
||||
* The replacement value that replaces found search values. An array may be used to
|
||||
* designate multiple replacements.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
abstract public function replace(Arrayable|Stringable|array|string $search, Arrayable|Stringable|array|string $replace): Text;
|
||||
|
||||
/**
|
||||
* Transforms the string to lowercase
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toLowerCase(): Text {
|
||||
return new Text(mb_strtolower($this->getString(), $this->encoding), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the string to first character lowercased
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toLowerCaseFirst(): Text {
|
||||
$first = $this->substring(0, 1);
|
||||
$rest = $this->substring(1);
|
||||
|
||||
return new Text(mb_strtolower((string) $first, $this->encoding) . $rest, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the string to uppercase
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toUpperCase(): Text {
|
||||
return new Text(mb_strtoupper($this->getString(), $this->encoding), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the string to first character uppercased
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toUpperCaseFirst(): Text {
|
||||
$first = $this->substring(0, 1);
|
||||
$rest = $this->substring(1);
|
||||
|
||||
return new Text(mb_strtoupper((string) $first, $this->encoding) . $rest, $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the string to only its first character capitalized.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toCapitalCase(): Text {
|
||||
return $this->toLowerCase()->toUpperCaseFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the string with the words capitalized.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toCapitalCaseWords(): Text {
|
||||
$encoding = $this->encoding;
|
||||
|
||||
return $this->split(' ')->map(function (string $str) use ($encoding) {
|
||||
return Text::create($str, $encoding)->toCapitalCase();
|
||||
})->join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this string into camelCase. Numbers are considered as part of its previous piece.
|
||||
*
|
||||
* <code>
|
||||
* $var = new Text('my_own_variable');<br>
|
||||
* $var->toCamelCase(); // myOwnVariable
|
||||
*
|
||||
* $var = new Text('my_test3_variable');<br>
|
||||
* $var->toCamelCase(); // myTest3Variable
|
||||
* </code>
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toCamelCase(): Text {
|
||||
return $this->toStudlyCase()->toLowerCaseFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this string into snake_case. Numbers are considered as part of its previous piece.
|
||||
*
|
||||
* <code>
|
||||
* $var = new Text('myOwnVariable');<br>
|
||||
* $var->toSnakeCase(); // my_own_variable
|
||||
*
|
||||
* $var = new Text('myTest3Variable');<br>
|
||||
* $var->toSnakeCase(); // my_test3_variable
|
||||
* </code>
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toSnakeCase(): Text {
|
||||
return $this->toKebabCase()->replace('-', '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this string into StudlyCase. Numbers are considered as part of its previous piece.
|
||||
*
|
||||
* <code>
|
||||
* $var = new Text('my_own_variable');<br>
|
||||
* $var->toStudlyCase(); // MyOwnVariable
|
||||
*
|
||||
* $var = new Text('my_test3_variable');<br>
|
||||
* $var->toStudlyCase(); // MyTest3Variable
|
||||
* </code>
|
||||
*
|
||||
* @return Text
|
||||
*
|
||||
* @psalm-suppress MixedArgument $matches[0] is a string
|
||||
*/
|
||||
public function toStudlyCase(): Text {
|
||||
$input = $this->trim('-_');
|
||||
if ($input->isEmpty()) {
|
||||
return $input;
|
||||
}
|
||||
$normString = preg_replace('/\s+/', ' ', $input->toString());
|
||||
$encoding = $this->encoding;
|
||||
|
||||
return Text::create(preg_replace_callback(
|
||||
'/([A-Z-_\s][a-z0-9]+)/',
|
||||
fn (array $matches): string => ucfirst(str_replace(['-', '_', ' '], '', $matches[0])),
|
||||
$normString
|
||||
), $encoding)
|
||||
->toUpperCaseFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this string into kebab-case. Numbers are considered as part of its previous piece.
|
||||
*
|
||||
* <code>
|
||||
* $var = new Text('myOwnVariable');<br>
|
||||
* $var->toKebabCase(); // my-own-variable
|
||||
*
|
||||
* $var = new Text('myTest3Variable');<br>
|
||||
* $var->toKebabCase(); // my-test3-variable
|
||||
* </code>
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toKebabCase(): Text {
|
||||
$input = $this->trim('-_');
|
||||
$normString = str_replace([' ', '_'], '-', preg_replace('/\s+/', ' ', $input->toString()));
|
||||
|
||||
return new Text(mb_strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1-$2', $normString)), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plural form of the Text object.
|
||||
*
|
||||
* @param InflectorInterface|null $pluralizer
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toPlural(?InflectorInterface $pluralizer = null): Text {
|
||||
$pluralizer = $pluralizer ?: new Inflector();
|
||||
|
||||
return new Text($pluralizer->getPluralForm($this->getString()), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singular form of the Text object.
|
||||
*
|
||||
* @param InflectorInterface|null $pluralizer
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function toSingular(?InflectorInterface $pluralizer = null): Text {
|
||||
$pluralizer = $pluralizer ?: new Inflector();
|
||||
|
||||
return new Text($pluralizer->getSingularForm($this->getString()), $this->encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts each tab in the string to some number of spaces, as defined by
|
||||
* $tabLength. By default, each tab is converted to 4 consecutive spaces.
|
||||
*
|
||||
* @param int $tabLength Number of spaces to replace each tab with
|
||||
*
|
||||
* @return Text text with tabs converted to spaces
|
||||
*/
|
||||
public function toSpaces(int $tabLength = 4): Text {
|
||||
$spaces = str_repeat(' ', $tabLength);
|
||||
|
||||
return $this->replace("\t", $spaces);
|
||||
}
|
||||
/**
|
||||
* Converts each occurrence of some consecutive number of spaces, as
|
||||
* defined by $tabLength, to a tab. By default, each 4 consecutive spaces
|
||||
* are converted to a tab.
|
||||
*
|
||||
* @param int $tabLength Number of spaces to replace with a tab
|
||||
*
|
||||
* @return Text text with spaces converted to tabs
|
||||
*/
|
||||
public function toTabs(int $tabLength = 4): Text {
|
||||
$spaces = str_repeat(' ', $tabLength);
|
||||
|
||||
return $this->replace($spaces, "\t");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user