allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

View File

@@ -0,0 +1,231 @@
<?php
namespace FedaPay\Util;
/**
* Class Inflector
*
* @package FedaPay\Util
*/
abstract class Inflector
{
/**
* Plural inflector rules
*
* @var array
*/
protected static $_plural = [
'/(s)tatus$/i' => '\1tatuses',
'/(quiz)$/i' => '\1zes',
'/^(ox)$/i' => '\1\2en',
'/([m|l])ouse$/i' => '\1ice',
'/(matr|vert|ind)(ix|ex)$/i' => '\1ices',
'/(x|ch|ss|sh)$/i' => '\1es',
'/([^aeiouy]|qu)y$/i' => '\1ies',
'/(hive)$/i' => '\1s',
'/(chef)$/i' => '\1s',
'/(?:([^f])fe|([lre])f)$/i' => '\1\2ves',
'/sis$/i' => 'ses',
'/([ti])um$/i' => '\1a',
'/(p)erson$/i' => '\1eople',
'/(?<!u)(m)an$/i' => '\1en',
'/(c)hild$/i' => '\1hildren',
'/(buffal|tomat)o$/i' => '\1\2oes',
'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin)us$/i' => '\1i',
'/us$/i' => 'uses',
'/(alias)$/i' => '\1es',
'/(ax|cris|test)is$/i' => '\1es',
'/s$/' => 's',
'/^$/' => '',
'/$/' => 's',
];
/**
* Singular inflector rules
*
* @var array
*/
protected static $_singular = [
'/(s)tatuses$/i' => '\1\2tatus',
'/^(.*)(menu)s$/i' => '\1\2',
'/(quiz)zes$/i' => '\\1',
'/(matr)ices$/i' => '\1ix',
'/(vert|ind)ices$/i' => '\1ex',
'/^(ox)en/i' => '\1',
'/(alias)(es)*$/i' => '\1',
'/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us',
'/([ftw]ax)es/i' => '\1',
'/(cris|ax|test)es$/i' => '\1is',
'/(shoe)s$/i' => '\1',
'/(o)es$/i' => '\1',
'/ouses$/' => 'ouse',
'/([^a])uses$/' => '\1us',
'/([m|l])ice$/i' => '\1ouse',
'/(x|ch|ss|sh)es$/i' => '\1',
'/(m)ovies$/i' => '\1\2ovie',
'/(s)eries$/i' => '\1\2eries',
'/([^aeiouy]|qu)ies$/i' => '\1y',
'/(tive)s$/i' => '\1',
'/(hive)s$/i' => '\1',
'/(drive)s$/i' => '\1',
'/([le])ves$/i' => '\1f',
'/([^rfoa])ves$/i' => '\1fe',
'/(^analy)ses$/i' => '\1sis',
'/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
'/([ti])a$/i' => '\1um',
'/(p)eople$/i' => '\1\2erson',
'/(m)en$/i' => '\1an',
'/(c)hildren$/i' => '\1\2hild',
'/(n)ews$/i' => '\1\2ews',
'/eaus$/' => 'eau',
'/^(.*us)$/' => '\\1',
'/s$/i' => ''
];
/**
* Irregular rules
*
* @var array
*/
protected static $_irregular = [
'atlas' => 'atlases',
'beef' => 'beefs',
'brief' => 'briefs',
'brother' => 'brothers',
'cafe' => 'cafes',
'child' => 'children',
'cookie' => 'cookies',
'corpus' => 'corpuses',
'cow' => 'cows',
'criterion' => 'criteria',
'ganglion' => 'ganglions',
'genie' => 'genies',
'genus' => 'genera',
'graffito' => 'graffiti',
'hoof' => 'hoofs',
'loaf' => 'loaves',
'man' => 'men',
'money' => 'monies',
'mongoose' => 'mongooses',
'move' => 'moves',
'mythos' => 'mythoi',
'niche' => 'niches',
'numen' => 'numina',
'occiput' => 'occiputs',
'octopus' => 'octopuses',
'opus' => 'opuses',
'ox' => 'oxen',
'penis' => 'penises',
'person' => 'people',
'sex' => 'sexes',
'soliloquy' => 'soliloquies',
'testis' => 'testes',
'trilby' => 'trilbys',
'turf' => 'turfs',
'potato' => 'potatoes',
'hero' => 'heroes',
'tooth' => 'teeth',
'goose' => 'geese',
'foot' => 'feet',
'foe' => 'foes',
'sieve' => 'sieves'
];
/**
* Words that should not be inflected
*
* @var array
*/
protected static $_uninflected = [
'.*[nrlm]ese', '.*data', '.*deer', '.*fish', '.*measles', '.*ois',
'.*pox', '.*sheep', 'people', 'feedback', 'stadia', '.*?media',
'chassis', 'clippers', 'debris', 'diabetes', 'equipment', 'gallows',
'graffiti', 'headquarters', 'information', 'innings', 'news', 'nexus',
'pokemon', 'proceedings', 'research', 'sea[- ]bass', 'series', 'species', 'weather'
];
/**
* Method cache array.
*
* @var array
*/
protected static $_cache = [];
/**
* Return $word in plural form.
*
* @param string $word Word in singular
* @return string Word in plural
*/
public static function pluralize($word)
{
if (isset(static::$_cache['pluralize'][$word])) {
return static::$_cache['pluralize'][$word];
}
if (!isset(static::$_cache['irregular']['pluralize'])) {
static::$_cache['irregular']['pluralize'] = '(?:' . implode('|', array_keys(static::$_irregular)) . ')';
}
if (preg_match('/(.*?(?:\\b|_))(' . static::$_cache['irregular']['pluralize'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $regs[1] . substr($regs[2], 0, 1) .
substr(static::$_irregular[strtolower($regs[2])], 1);
return static::$_cache['pluralize'][$word];
}
if (!isset(static::$_cache['uninflected'])) {
static::$_cache['uninflected'] = '(?:' . implode('|', static::$_uninflected) . ')';
}
if (preg_match('/^(' . static::$_cache['uninflected'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $word;
return $word;
}
foreach (static::$_plural as $rule => $replacement) {
if (preg_match($rule, $word)) {
static::$_cache['pluralize'][$word] = preg_replace($rule, $replacement, $word);
return static::$_cache['pluralize'][$word];
}
}
}
/**
* Return $word in singular form.
*
* @param string $word Word in plural
* @return string Word in singular
* @link https://book.cakephp.org/3.0/en/core-libraries/inflector.html#creating-plural-singular-forms
*/
public static function singularize($word)
{
if (isset(static::$_cache['singularize'][$word])) {
return static::$_cache['singularize'][$word];
}
if (!isset(static::$_cache['irregular']['singular'])) {
static::$_cache['irregular']['singular'] = '(?:' . implode('|', static::$_irregular) . ')';
}
if (preg_match('/(.*?(?:\\b|_))(' . static::$_cache['irregular']['singular'] . ')$/i', $word, $regs)) {
static::$_cache['singularize'][$word] = $regs[1] . substr($regs[2], 0, 1) .
substr(array_search(strtolower($regs[2]), static::$_irregular), 1);
return static::$_cache['singularize'][$word];
}
if (!isset(static::$_cache['uninflected'])) {
static::$_cache['uninflected'] = '(?:' . implode('|', static::$_uninflected) . ')';
}
if (preg_match('/^(' . static::$_cache['uninflected'] . ')$/i', $word, $regs)) {
static::$_cache['pluralize'][$word] = $word;
return $word;
}
foreach (static::$_singular as $rule => $replacement) {
if (preg_match($rule, $word)) {
static::$_cache['singularize'][$word] = preg_replace($rule, $replacement, $word);
return static::$_cache['singularize'][$word];
}
}
static::$_cache['singularize'][$word] = $word;
return $word;
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace FedaPay\Util;
/**
* A basic random generator. This is in a separate class so we the generator
* can be injected as a dependency and replaced with a mock in tests.
*/
class RandomGenerator
{
/**
* Returns a random value between 0 and $max.
*
* @param float $max (optional)
* @return float
*/
public function randFloat($max = 1.0)
{
return mt_rand() / mt_getrandmax() * $max;
}
/**
* Returns a v4 UUID.
*
* @return string
*/
public function uuid()
{
$arr = array_values(unpack('N1a/n4b/N1c', openssl_random_pseudo_bytes(16)));
$arr[2] = ($arr[2] & 0x0fff) | 0x4000;
$arr[3] = ($arr[3] & 0x3fff) | 0x8000;
return vsprintf('%08x-%04x-%04x-%04x-%04x%08x', $arr);
}
}

View File

@@ -0,0 +1,255 @@
<?php
namespace FedaPay\Util;
use FedaPay\FedaPayObject;
/**
* Class Util
*
* @package FedaPay\Util
*/
abstract class Util
{
private static $isMbstringAvailable = null;
private static $isHashEqualsAvailable = null;
/**
* Whether the provided array (or other) is a list rather than a dictionary.
*
* @param array|mixed $array
* @return boolean True if the given object is a list.
*/
public static function isList($array)
{
if (!is_array($array)) {
return false;
}
if ($array === []) {
return true;
}
if (array_keys($array) !== range(0, count($array) - 1)) {
return false;
}
return true;
}
/**
* Convert a a response to fedapay object
* @param array $resp The response object
* @param array $opts Additional options.
*
* @return \FedaPay\FedaPayObject
*/
public static function convertToFedaPayObject($resp, $opts)
{
$types = [
'v1/api_key' => 'FedaPay\\ApiKey',
'v1/account' => 'FedaPay\\Account',
'v1/currency' => 'FedaPay\\Currency',
'v1/customer' => 'FedaPay\\Customer',
'v1/event' => 'FedaPay\\Event',
'v1/log' => 'FedaPay\\Log',
'v1/phone_number' => 'FedaPay\\PhoneNumber',
'v1/transaction' => 'FedaPay\\Transaction',
'v1/payout' => 'FedaPay\\Payout',
'v1/page' => 'FedaPay\\Page',
'v1/invoice' => 'FedaPay\\Invoice',
'v1/balance' => 'FedaPay\\Balance',
];
if (self::isList($resp)) {
$mapped = [];
foreach ($resp as $i) {
array_push($mapped, self::arrayToFedaPayObject($i, $opts));
}
return $mapped;
} elseif (is_array($resp)) {
if (isset($resp['klass']) && is_string($resp['klass']) && isset($types[$resp['klass']])) {
$class = $types[$resp['klass']];
} else {
$class = FedaPayObject::class;
}
$object = new $class;
$object->refreshFrom($resp, $opts);
return $object;
} else {
return $resp;
}
}
/**
* Converts an array to FedaPay object.
*
* @param array $array The PHP array to convert.
* @param array $opts Additional options.
*
* @return \FedaPay\FedaPayObject
*/
public static function arrayToFedaPayObject($array, $opts)
{
if (self::isList($array)) {
$mapped = array();
foreach ($array as $i) {
array_push($mapped, self::convertToFedaPayObject($i, $opts));
}
return $mapped;
} else {
return self::convertToFedaPayObject($array, $opts);
}
}
/**
* Recursively converts the PHP FedaPay object to an array.
*
* @param array $values The PHP FedaPay object to convert.
* @return array
*/
public static function convertFedaPayObjectToArray($values)
{
$results = [];
foreach ($values as $k => $v) {
if ($v instanceof FedaPayObject) {
$results[$k] = $v->__toArray(true);
} elseif (is_array($v)) {
$results[$k] = self::convertFedaPayObjectToArray($v);
} else {
$results[$k] = $v;
}
}
return $results;
}
/**
* Strip api version from key
* @param string $key
* @param array $opts
*
* @return string
*/
public static function stripApiVersion($key, $opts)
{
$apiPart = '';
if (is_array($opts) && isset($opts['apiVersion'])) {
$apiPart = $opts['apiVersion'] . '/';
}
return str_replace($apiPart, '', $key);
}
/**
* Check a date falue
* @param mixed $date
* @return mixed
*/
public static function toDateString($date)
{
if ($date instanceof \DateTime) {
return $date->format('Y-m-d H:i:s');
} else if (is_string($date) || is_int($date)) {
return $date;
} else {
throw new \InvalidArgumentException(
'Invalid datetime argument. Should be a date in string format, '
.' a timestamp or an instance of \DateTime.'
);
}
}
/**
* @param array $params
*
* @return string
*/
public static function encodeParameters($params)
{
$flattenedParams = [];
self::flattenParams($params, $flattenedParams);
$pieces = [];
foreach ($flattenedParams as $param) {
list($k, $v) = $param;
array_push($pieces, self::urlEncode($k) . '=' . self::urlEncode($v));
}
return implode('&', $pieces);
}
/**
* Flattens the array so that it can be used with curl.
*
* @param $arrays
* @param array $new
* @param null $prefix
*/
public static function flattenParams($arrays, &$new = array(), $prefix = null)
{
$isList = self::isList($arrays);
foreach ($arrays as $key => $value) {
if (isset($prefix) && $isList) {
$k = $prefix.'[]';
} elseif (isset($prefix)) {
$k = $prefix.'['.$key.']';
} else {
$k = $key;
}
if (is_array($value)) {
self::flattenParams($value, $new, $k);
} else {
array_push($new, [$k, $value]);
}
}
}
/**
* @param string $key A string to URL-encode.
*
* @return string The URL-encoded string.
*/
public static function urlEncode($key)
{
$s = urlencode($key);
// Don't use strict form encoding by changing the square bracket control
// characters back to their literals. This is fine by the server, and
// makes these parameter strings easier to read.
$s = str_replace('%5B', '[', $s);
$s = str_replace('%5D', ']', $s);
return $s;
}
/**
* Compares two strings for equality. The time taken is independent of the
* number of characters that match.
*
* @param string $a one of the strings to compare.
* @param string $b the other string to compare.
* @return bool true if the strings are equal, false otherwise.
*/
public static function secureCompare($a, $b)
{
if (self::$isHashEqualsAvailable === null) {
self::$isHashEqualsAvailable = function_exists('hash_equals');
}
if (self::$isHashEqualsAvailable) {
return hash_equals($a, $b);
} else {
if (strlen($a) != strlen($b)) {
return false;
}
$result = 0;
for ($i = 0; $i < strlen($a); $i++) {
$result |= ord($a[$i]) ^ ord($b[$i]);
}
return ($result == 0);
}
}
}