Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<?php
namespace FluentMail\Includes;
class Activator
{
public static function handle($network_wide = false)
{
require_once(FLUENTMAIL_PLUGIN_PATH . 'database/FluentMailDBMigrator.php');
$emailReportHookName = 'fluentmail_do_daily_scheduled_tasks';
if (!wp_next_scheduled($emailReportHookName)) {
wp_schedule_event(time(), 'daily', $emailReportHookName);
}
add_filter('pre_update_option_active_plugins', function ($plugins) {
$index = array_search('fluent-smtp/fluent-smtp.php', $plugins);
if ($index !== false) {
if ($index === 0) {
return $plugins;
}
unset($plugins[$index]);
array_unshift($plugins, 'fluent-smtp/fluent-smtp.php');
}
return $plugins;
});
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace FluentMail\Includes\Core;
use ArrayAccess;
use FluentMail\Includes\View\View;
use FluentMail\Includes\Core\CoreTrait;
use FluentMail\Includes\Core\Container;
use FluentMail\Includes\Request\Request;
use FluentMail\Includes\Response\Response;
final class Application extends Container
{
use CoreTrait;
private $policyNamespace = 'FluentMail\App\Http\Policies';
private $handlerNamespace = 'FluentMail\App\Hooks\Handlers';
private $controllerNamespace = 'FluentMail\App\Http\Controllers';
public function __construct()
{
$this->setApplicationInstance();
$this->registerPluginPathsAndUrls();
$this->registerFrameworkComponents();
$this->requireCommonFilesForRequest($this);
load_plugin_textdomain('fluent-smtp', false, 'fluent-smtp/language/');
/*
* We are adding fluent-smtp/fluent-smtp.php at the top to load the wp_mail at the very first
* There has no other way to load a specific plugin at the first.
*/
add_filter('pre_update_option_active_plugins', function ($plugins) {
$index = array_search('fluent-smtp/fluent-smtp.php', $plugins);
if ($index !== false) {
if ($index === 0) {
return $plugins;
}
unset($plugins[$index]);
array_unshift($plugins, 'fluent-smtp/fluent-smtp.php');
}
return $plugins;
});
add_action('admin_notices', function () {
if (!current_user_can('manage_options')) {
return;
}
$settings = get_option('fluentmail-settings');
if (!$settings || empty($settings['use_encrypt']) || empty($settings['test'])) {
return;
}
$testData = fluentMailEncryptDecrypt($settings['test'], 'd');
if ($testData == 'test') {
return;
}
?>
<div class="notice notice-warning fluentsmtp_urgent is-dismissible">
<p>
FluentSMTP Plugin may not work properly. Looks like your Authentication unique keys and salts are changed. <a href="<?php echo esc_url(admin_url('options-general.php?page=fluent-mail#/connections')); ?>"><b>Reconfigure SMTP Settings</b></a>
</p>
</div>
<?php
});
}
private function setApplicationInstance()
{
static::setInstance($this);
$this->instance('app', $this);
$this->instance(__CLASS__, $this);
}
private function registerPluginPathsAndUrls()
{
// Paths
$this['path'] = FLUENTMAIL_PLUGIN_PATH;
$this['path.app'] = FLUENTMAIL_PLUGIN_PATH . 'app/';
$this['path.hooks'] = FLUENTMAIL_PLUGIN_PATH . 'app/Hooks/';
$this['path.models'] = FLUENTMAIL_PLUGIN_PATH . 'app/models/';
$this['path.includes'] = FLUENTMAIL_PLUGIN_PATH . 'includes/';
$this['path.controllers'] = FLUENTMAIL_PLUGIN_PATH . 'app/Http/controllers/';
$this['path.views'] = FLUENTMAIL_PLUGIN_PATH . 'app/views/';
$this['path.admin.css'] = FLUENTMAIL_PLUGIN_PATH . 'assets/admin/css/';
$this['path.admin.js'] = FLUENTMAIL_PLUGIN_PATH . 'assets/admin/js/';
$this['path.public.css'] = FLUENTMAIL_PLUGIN_PATH . 'assets/public/css/';
$this['path.public.js'] = FLUENTMAIL_PLUGIN_PATH . 'assets/public/js/';
$this['path.assets'] = FLUENTMAIL_PLUGIN_PATH . 'assets/';
// Urls
$this['url'] = FLUENTMAIL_PLUGIN_URL;
$this['url.app'] = FLUENTMAIL_PLUGIN_URL . 'app/';
$this['url.assets'] = FLUENTMAIL_PLUGIN_URL . 'assets/';
$this['url.public.css'] = FLUENTMAIL_PLUGIN_URL . 'assets/public/css/';
$this['url.admin.css'] = FLUENTMAIL_PLUGIN_URL . 'assets/admin/css/';
$this['url.public.js'] = FLUENTMAIL_PLUGIN_URL . 'assets/public/js/';
$this['url.admin.js'] = FLUENTMAIL_PLUGIN_URL . 'assets/admin/js/';
$this['url.assets.images'] = FLUENTMAIL_PLUGIN_URL . 'assets/images/';
}
private function registerFrameworkComponents()
{
$this->bind('FluentMail\Includes\View\View', function ($app) {
return new View($app);
});
$this->alias('FluentMail\Includes\View\View', 'view');
$this->singleton('FluentMail\Includes\Request\Request', function ($app) {
return new Request($app, $_GET, $_POST, $_FILES);
});
$this->alias('FluentMail\Includes\Request\Request', 'request');
$this->singleton('FluentMail\Includes\Response\Response', function ($app) {
return new Response($app);
});
$this->alias('FluentMail\Includes\Response\Response', 'response');
}
/**
* Require all the common files that needs to be loaded on each request
*
* @param Application $app [$app is being used inside required files]
* @return void
*/
private function requireCommonFilesForRequest($app)
{
// Require Application Bindings
require_once($app['path.app'] . '/Bindings.php');
// Require Global Functions
require_once($app['path.app'] . '/Functions/helpers.php');
// Require Action Hooks
require_once($app['path.app'] . '/Hooks/actions.php');
// Require Filter Hooks
require_once($app['path.app'] . '/Hooks/filters.php');
// Require Routes
if (is_admin()) {
require_once($app['path.app'] . '/Http/routes.php');
}
}
}

View File

@@ -0,0 +1,5 @@
<?php
namespace FluentMail\Includes\Core;
class BindingResolutionException extends \Exception {}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
<?php
namespace FluentMail\Includes\Core;
use Closure;
interface ContainerContract
{
/**
* Determine if the given abstract type has been bound.
*
* @param string $abstract
* @return bool
*/
public function bound($abstract);
/**
* Alias a type to a different name.
*
* @param string $abstract
* @param string $alias
* @return void
*/
public function alias($abstract, $alias);
/**
* Assign a set of tags to a given binding.
*
* @param array|string $abstracts
* @param array|mixed ...$tags
* @return void
*/
public function tag($abstracts, $tags);
/**
* Resolve all of the bindings for a given tag.
*
* @param array $tag
* @return array
*/
public function tagged($tag);
/**
* Register a binding with the container.
*
* @param string|array $abstract
* @param Closure|string|null $concrete
* @param bool $shared
* @return void
*/
public function bind($abstract, $concrete = null, $shared = false);
/**
* Register a binding if it hasn't already been registered.
*
* @param string $abstract
* @param Closure|string|null $concrete
* @param bool $shared
* @return void
*/
public function bindIf($abstract, $concrete = null, $shared = false);
/**
* Register a shared binding in the container.
*
* @param string $abstract
* @param Closure|string|null $concrete
* @return void
*/
public function singleton($abstract, $concrete = null);
/**
* "Extend" an abstract type in the container.
*
* @param string $abstract
* @param Closure $closure
* @return void
*
* @throws \InvalidArgumentException
*/
public function extend($abstract, Closure $closure);
/**
* Register an existing instance as shared in the container.
*
* @param string $abstract
* @param mixed $instance
* @return void
*/
public function instance($abstract, $instance);
/**
* Define a contextual binding.
*
* @param string $concrete
* @return ContextualBindingBuilder
*/
public function when($concrete);
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function make($abstract, $parameters = array());
/**
* Call the given Closure / class@method and inject its dependencies.
*
* @param callable|string $callback
* @param array $parameters
* @param string|null $defaultMethod
* @return mixed
*/
public function call($callback, array $parameters = array(), $defaultMethod = null);
/**
* Determine if the given abstract type has been resolved.
*
* @param string $abstract
* @return bool
*/
public function resolved($abstract);
/**
* Register a new resolving callback.
*
* @param string $abstract
* @param Closure $callback
* @return void
*/
public function resolving($abstract, ?Closure $callback = null);
/**
* Register a new after resolving callback.
*
* @param string $abstract
* @param Closure $callback
* @return void
*/
public function afterResolving($abstract, ?Closure $callback = null);
}

View File

@@ -0,0 +1,60 @@
<?php
namespace FluentMail\Includes\Core;
use FluentMail\Includes\Support\Contracts\ContextualBindingBuilderContract;
class ContextualBindingBuilder implements ContextualBindingBuilderContract
{
/**
* The underlying container instance.
*
* @var FluentMail\Includes\Core\Container
*/
protected $container;
/**
* The concrete instance.
*
* @var string
*/
protected $concrete;
/**
* Create a new contextual binding builder.
*
* @param FluentMail\Includes\Core\Container $container
* @param string $concrete
* @return void
*/
public function __construct(Container $container, $concrete)
{
$this->concrete = $concrete;
$this->container = $container;
}
/**
* Define the abstract target that depends on the context.
*
* @param string $abstract
* @return $this
*/
public function needs($abstract)
{
$this->needs = $abstract;
return $this;
}
/**
* Define the implementation for the contextual binding.
*
* @param Closure|string $implementation
* @return void
*/
public function give($implementation)
{
$this->container->addContextualBinding(
$this->concrete, $this->needs, $implementation
);
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace FluentMail\Includes\Core;
use FluentMail\Includes\Support\ForbiddenException;
trait CoreTrait
{
public function get($action, $handler, $isAdmin = true)
{
$action = $this->getAjaxAction($action, 'get', $isAdmin);
return add_action($action, $this->parseAjaxHandler($handler));
}
public function getPublic($action, $handler)
{
$this->get($action, $handler, false);
}
public function post($action, $handler, $isAdmin = true)
{
$action = $this->getAjaxAction($action, 'post', $isAdmin);
return add_action($action, function() use ($handler) {
try {
$slug = FLUENTMAIL;
if (check_ajax_referer($slug, 'nonce', false)) {
$method = $this->parseAjaxHandler($handler);
return $method();
}
throw new ForbiddenException('Forbidden!', 401);
} catch (ForbiddenException $e) {
return $this->docustomAction('handle_exception', $e);
}
});
}
public function postPublic($action, $handler)
{
$this->post($action, $handler, false);
}
public function getAjaxAction($action, $method, $isAdmin)
{
$context = $isAdmin ? 'wp_ajax_' : 'wp_ajax_nopriv_';
$action = $action == '/' ? $action : ltrim($action, '/');
return $context.$this->hook($method.'-'.$action);
}
public function hook($hook)
{
return FLUENTMAIL . '-' . $hook;
}
public function parseAjaxHandler($handler)
{
if (!$handler) return;
if (is_string($handler)) {
$handler = $this->controllerNamespace . '\\' . $handler;
} else if (is_array($handler)) {
list($class, $method) = $handler;
if (is_string($class)) {
$handler = $this->controllerNamespace . '\\' . $class . '::' . $method;
}
}
return function() use ($handler) {
return $this->call($handler);
};
}
public function addAction($action, $handler, $priority = 10, $numOfArgs = 1)
{
return add_action(
$action,
$this->parseHookHandler($handler),
$priority,
$numOfArgs
);
}
public function addCustomAction($action, $handler, $priority = 10, $numOfArgs = 1)
{
return $this->addAction($this->hook($action), $handler, $priority, $numOfArgs);
}
public function doAction()
{
return call_user_func_array('do_action', func_get_args());
}
public function doCustomAction()
{
$args = func_get_args();
$args[0] = $this->hook($args[0]);
return call_user_func_array('do_action', $args);
}
public function addFilter($action, $handler, $priority = 10, $numOfArgs = 1)
{
return add_filter(
$action,
$this->parseHookHandler($handler),
$priority,
$numOfArgs
);
}
public function addCustomFilter($action, $handler, $priority = 10, $numOfArgs = 1)
{
return $this->addFilter($this->hook($action), $handler, $priority, $numOfArgs);
}
public function applyFilters()
{
return call_user_func_array('apply_filters', func_get_args());
}
public function applyCustomFilters()
{
$args = func_get_args();
$args[0] = $this->hook($args[0]);
return call_user_func_array('apply_filters', $args);
}
public function parseHookHandler($handler)
{
if (is_string($handler)) {
list($class, $method) = preg_split('/::|@/', $handler);
if ($this->hasNamespace($handler)) {
$class = $this->make($class);
} else {
$class = $this->make($this->handlerNamespace . '\\' . $class);
}
return [$class, $method];
} else if (is_array($handler)) {
list($class, $method) = $handler;
if (is_string($class)) {
if ($this->hasNamespace($handler)) {
$class = $this->make($class);
} else {
$class = $this->make($this->handlerNamespace . '\\' . $class);
}
}
return [$class, $method];
}
return $handler;
}
public function hasNamespace($handler)
{
$parts = explode('\\', $handler);
return count($parts) > 1;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace FluentMail\Includes\Core;
use ReflectionParameter;
use ReflectionNamedType;
class Reflection
{
private static function isPhp8OrHigher()
{
return PHP_VERSION_ID >= 80000;
}
public static function getClassName(ReflectionParameter $parameter)
{
if (static::isPhp8OrHigher()) {
$type = $parameter->getType();
if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
return $type->getName();
}
return null;
}
$class = $parameter->getClass();
return $class ? $class->getName() : null;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace FluentMail\Includes;
class Deactivator
{
public static function handle($network_wide = false)
{
wp_clear_scheduled_hook('fluentmail_do_daily_scheduled_tasks');
}
}

View File

@@ -0,0 +1,258 @@
<?php
namespace FluentMail\Includes;
class OAuth2Provider
{
private $options;
private $accessTokenMethod = 'POST';
const METHOD_GET = 'GET';
public function __construct($options = [])
{
$this->assertRequiredOptions($options);
$this->options = $options;
}
public function getAuthorizationUrl($options = [])
{
$base = $this->options['urlAuthorize'];
$params = $this->getAuthorizationParameters($options);
$query = $this->getAuthorizationQuery($params);
return $this->appendQuery($base, $query);
}
private function getAuthorizationParameters($options)
{
if (empty($options['state'])) {
$options['state'] = $this->getRandomState();
}
if (empty($options['scope'])) {
$options['scope'] = $this->options['scopes'];
}
$options += [
'response_type' => 'code',
'approval_prompt' => 'auto'
];
if (is_array($options['scope'])) {
$separator = ',';
$options['scope'] = implode($separator, $options['scope']);
}
// Store the state as it may need to be accessed later on.
$this->options['state'] = $options['state'];
// Business code layer might set a different redirect_uri parameter
// depending on the context, leave it as-is
if (!isset($options['redirect_uri'])) {
$options['redirect_uri'] = $this->options['redirectUri'];
}
$options['client_id'] = $this->options['clientId'];
return $options;
}
/**
* Appends a query string to a URL.
*
* @param string $url The URL to append the query to
* @param string $query The HTTP query string
* @return string The resulting URL
*/
protected function appendQuery($url, $query)
{
$query = trim($query, '?&');
if ($query) {
$glue = strstr($url, '?') === false ? '?' : '&';
return $url . $glue . $query;
}
return $url;
}
/**
* Builds the authorization URL's query string.
*
* @param array $params Query parameters
* @return string Query string
*/
protected function getAuthorizationQuery(array $params)
{
return $this->buildQueryString($params);
}
/**
* Build a query string from an array.
*
* @param array $params
*
* @return string
*/
protected function buildQueryString(array $params)
{
return http_build_query($params, '', '&', \PHP_QUERY_RFC3986);
}
/**
* Verifies that all required options have been passed.
*
* @param array $options
* @return void
* @throws \InvalidArgumentException
*/
private function assertRequiredOptions(array $options)
{
$missing = array_diff_key(array_flip($this->getRequiredOptions()), $options);
if (!empty($missing)) {
throw new \InvalidArgumentException(
'Required options not defined: ' . implode(', ', array_keys($missing)) // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
);
}
}
/**
* Returns all options that are required.
*
* @return array
*/
protected function getRequiredOptions()
{
return [
'urlAuthorize',
'urlAccessToken',
'urlResourceOwnerDetails',
];
}
/**
* Returns a new random string to use as the state parameter in an
* authorization flow.
*
* @param int $length Length of the random string to be generated.
* @return string
*/
protected function getRandomState($length = 32)
{
// Converting bytes to hex will always double length. Hence, we can reduce
// the amount of bytes by half to produce the correct length.
$state = bin2hex(random_bytes($length / 2));
update_option('_fluentmail_last_generated_state', $state);
return $state;
}
/**
* Requests an access token using a specified grant and option set.
*
* @param mixed $grant
* @param array $options
* @throws \Exception
* @return array tokens
*/
public function getAccessToken($grant, array $options = [])
{
$params = [
'client_id' => $this->options['clientId'],
'client_secret' => $this->options['clientSecret'],
'redirect_uri' => $this->options['redirectUri'],
'grant_type' => $grant,
];
$params += $options;
$requestData = $this->getAccessTokenRequestDetails($params);
$response = wp_remote_request($requestData['url'], $requestData['params']);
if (is_wp_error($response)) {
throw new \Exception(
wp_kses_post($response->get_error_message())
);
}
$responseBody = wp_remote_retrieve_body($response);
if (false === is_array($response)) {
throw new \Exception(
'Invalid response received from Authorization Server. Expected JSON.'
);
}
if(empty(['access_token'])) {
throw new \Exception(
'Invalid response received from Authorization Server.'
);
}
return \json_decode($responseBody, true);
}
/**
* Returns a prepared request for requesting an access token.
*
* @param array $params Query string parameters
* @return array $requestDetails
*/
protected function getAccessTokenRequestDetails($params)
{
$method = $this->accessTokenMethod;
$url = $this->getAccessTokenUrl($params);
$options = $this->buildQueryString($params);
return [
'url' => $url,
'params' => [
'method' => $method,
'body' => $options,
'headers' => [
'content-type' => 'application/x-www-form-urlencoded'
]
]
];
}
/**
* Returns the full URL to use when requesting an access token.
*
* @param array $params Query parameters
* @return string
*/
protected function getAccessTokenUrl($params)
{
$url = $this->options['urlAccessToken'];
if ($this->accessTokenMethod === self::METHOD_GET) {
$query = $this->getAccessTokenQuery($params);
return $this->appendQuery($url, $query);
}
return $url;
}
/**
* Builds the access token URL's query string.
*
* @param array $params Query parameters
* @return string Query string
*/
protected function getAccessTokenQuery(array $params)
{
return $this->buildQueryString($params);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace FluentMail\Includes\Request;
trait Cleaner
{
/**
* Clean up the request data.
*
* @param array $data
* @return array
*/
public function clean($data)
{
return $this->cleanArray($data);
}
/**
* Clean the data in the given array.
*
* @param array $data
* @return array
*/
protected function cleanArray(array $data)
{
return array_map(function ($value) {
return $this->cleanValue($value);
}, $data);
}
/**
* Clean the given value.
*
* @param mixed $value
* @return mixed
*/
protected function cleanValue($value)
{
if (is_array($value)) {
return $this->cleanArray($value);
}
return $this->transform($value);
}
/**
* Transform the given value.
*
* @param mixed $value
* @return mixed
*/
protected function transform($value)
{
if (is_string($value)) {
$value = trim($value);
if ($value === '') {
$value = null;
}
}
return $value;
}
}

View File

@@ -0,0 +1,956 @@
<?php
namespace FluentMail\Includes\Request;
use SplFileInfo;
use FluentMail\includes\Support\Contracts\FileInterface;
class File extends SplFileInfo implements FileInterface
{
/**
* A map of mime types and their default extensions.
*
* This list has been placed under the public domain by the Apache HTTPD project.
* This list has been updated from upstream on 2013-04-23.
*
* @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
*/
protected $defaultExtensions = [
'application/andrew-inset' => 'ez',
'application/applixware' => 'aw',
'application/atom+xml' => 'atom',
'application/atomcat+xml' => 'atomcat',
'application/atomsvc+xml' => 'atomsvc',
'application/ccxml+xml' => 'ccxml',
'application/cdmi-capability' => 'cdmia',
'application/cdmi-container' => 'cdmic',
'application/cdmi-domain' => 'cdmid',
'application/cdmi-object' => 'cdmio',
'application/cdmi-queue' => 'cdmiq',
'application/cu-seeme' => 'cu',
'application/davmount+xml' => 'davmount',
'application/docbook+xml' => 'dbk',
'application/dssc+der' => 'dssc',
'application/dssc+xml' => 'xdssc',
'application/ecmascript' => 'ecma',
'application/emma+xml' => 'emma',
'application/epub+zip' => 'epub',
'application/exi' => 'exi',
'application/font-tdpfr' => 'pfr',
'application/gml+xml' => 'gml',
'application/gpx+xml' => 'gpx',
'application/gxf' => 'gxf',
'application/hyperstudio' => 'stk',
'application/inkml+xml' => 'ink',
'application/ipfix' => 'ipfix',
'application/java-archive' => 'jar',
'application/java-serialized-object' => 'ser',
'application/java-vm' => 'class',
'application/javascript' => 'js',
'application/json' => 'json',
'application/jsonml+json' => 'jsonml',
'application/lost+xml' => 'lostxml',
'application/mac-binhex40' => 'hqx',
'application/mac-compactpro' => 'cpt',
'application/mads+xml' => 'mads',
'application/marc' => 'mrc',
'application/marcxml+xml' => 'mrcx',
'application/mathematica' => 'ma',
'application/mathml+xml' => 'mathml',
'application/mbox' => 'mbox',
'application/mediaservercontrol+xml' => 'mscml',
'application/metalink+xml' => 'metalink',
'application/metalink4+xml' => 'meta4',
'application/mets+xml' => 'mets',
'application/mods+xml' => 'mods',
'application/mp21' => 'm21',
'application/mp4' => 'mp4s',
'application/msword' => 'doc',
'application/mxf' => 'mxf',
'application/octet-stream' => 'bin',
'application/oda' => 'oda',
'application/oebps-package+xml' => 'opf',
'application/ogg' => 'ogx',
'application/omdoc+xml' => 'omdoc',
'application/onenote' => 'onetoc',
'application/oxps' => 'oxps',
'application/patch-ops-error+xml' => 'xer',
'application/pdf' => 'pdf',
'application/pgp-encrypted' => 'pgp',
'application/pgp-signature' => 'asc',
'application/pics-rules' => 'prf',
'application/pkcs10' => 'p10',
'application/pkcs7-mime' => 'p7m',
'application/pkcs7-signature' => 'p7s',
'application/pkcs8' => 'p8',
'application/pkix-attr-cert' => 'ac',
'application/pkix-cert' => 'cer',
'application/pkix-crl' => 'crl',
'application/pkix-pkipath' => 'pkipath',
'application/pkixcmp' => 'pki',
'application/pls+xml' => 'pls',
'application/postscript' => 'ai',
'application/prs.cww' => 'cww',
'application/pskc+xml' => 'pskcxml',
'application/rdf+xml' => 'rdf',
'application/reginfo+xml' => 'rif',
'application/relax-ng-compact-syntax' => 'rnc',
'application/resource-lists+xml' => 'rl',
'application/resource-lists-diff+xml' => 'rld',
'application/rls-services+xml' => 'rs',
'application/rpki-ghostbusters' => 'gbr',
'application/rpki-manifest' => 'mft',
'application/rpki-roa' => 'roa',
'application/rsd+xml' => 'rsd',
'application/rss+xml' => 'rss',
'application/rtf' => 'rtf',
'application/sbml+xml' => 'sbml',
'application/scvp-cv-request' => 'scq',
'application/scvp-cv-response' => 'scs',
'application/scvp-vp-request' => 'spq',
'application/scvp-vp-response' => 'spp',
'application/sdp' => 'sdp',
'application/set-payment-initiation' => 'setpay',
'application/set-registration-initiation' => 'setreg',
'application/shf+xml' => 'shf',
'application/smil+xml' => 'smi',
'application/sparql-query' => 'rq',
'application/sparql-results+xml' => 'srx',
'application/srgs' => 'gram',
'application/srgs+xml' => 'grxml',
'application/sru+xml' => 'sru',
'application/ssdl+xml' => 'ssdl',
'application/ssml+xml' => 'ssml',
'application/tei+xml' => 'tei',
'application/thraud+xml' => 'tfi',
'application/timestamped-data' => 'tsd',
'application/vnd.3gpp.pic-bw-large' => 'plb',
'application/vnd.3gpp.pic-bw-small' => 'psb',
'application/vnd.3gpp.pic-bw-var' => 'pvb',
'application/vnd.3gpp2.tcap' => 'tcap',
'application/vnd.3m.post-it-notes' => 'pwn',
'application/vnd.accpac.simply.aso' => 'aso',
'application/vnd.accpac.simply.imp' => 'imp',
'application/vnd.acucobol' => 'acu',
'application/vnd.acucorp' => 'atc',
'application/vnd.adobe.air-application-installer-package+zip' => 'air',
'application/vnd.adobe.formscentral.fcdt' => 'fcdt',
'application/vnd.adobe.fxp' => 'fxp',
'application/vnd.adobe.xdp+xml' => 'xdp',
'application/vnd.adobe.xfdf' => 'xfdf',
'application/vnd.ahead.space' => 'ahead',
'application/vnd.airzip.filesecure.azf' => 'azf',
'application/vnd.airzip.filesecure.azs' => 'azs',
'application/vnd.amazon.ebook' => 'azw',
'application/vnd.americandynamics.acc' => 'acc',
'application/vnd.amiga.ami' => 'ami',
'application/vnd.android.package-archive' => 'apk',
'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
'application/vnd.antix.game-component' => 'atx',
'application/vnd.apple.installer+xml' => 'mpkg',
'application/vnd.apple.mpegurl' => 'm3u8',
'application/vnd.aristanetworks.swi' => 'swi',
'application/vnd.astraea-software.iota' => 'iota',
'application/vnd.audiograph' => 'aep',
'application/vnd.blueice.multipass' => 'mpm',
'application/vnd.bmi' => 'bmi',
'application/vnd.businessobjects' => 'rep',
'application/vnd.chemdraw+xml' => 'cdxml',
'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
'application/vnd.cinderella' => 'cdy',
'application/vnd.claymore' => 'cla',
'application/vnd.cloanto.rp9' => 'rp9',
'application/vnd.clonk.c4group' => 'c4g',
'application/vnd.cluetrust.cartomobile-config' => 'c11amc',
'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz',
'application/vnd.commonspace' => 'csp',
'application/vnd.contact.cmsg' => 'cdbcmsg',
'application/vnd.cosmocaller' => 'cmc',
'application/vnd.crick.clicker' => 'clkx',
'application/vnd.crick.clicker.keyboard' => 'clkk',
'application/vnd.crick.clicker.palette' => 'clkp',
'application/vnd.crick.clicker.template' => 'clkt',
'application/vnd.crick.clicker.wordbank' => 'clkw',
'application/vnd.criticaltools.wbs+xml' => 'wbs',
'application/vnd.ctc-posml' => 'pml',
'application/vnd.cups-ppd' => 'ppd',
'application/vnd.curl.car' => 'car',
'application/vnd.curl.pcurl' => 'pcurl',
'application/vnd.dart' => 'dart',
'application/vnd.data-vision.rdz' => 'rdz',
'application/vnd.dece.data' => 'uvf',
'application/vnd.dece.ttml+xml' => 'uvt',
'application/vnd.dece.unspecified' => 'uvx',
'application/vnd.dece.zip' => 'uvz',
'application/vnd.denovo.fcselayout-link' => 'fe_launch',
'application/vnd.dna' => 'dna',
'application/vnd.dolby.mlp' => 'mlp',
'application/vnd.dpgraph' => 'dpg',
'application/vnd.dreamfactory' => 'dfac',
'application/vnd.ds-keypoint' => 'kpxx',
'application/vnd.dvb.ait' => 'ait',
'application/vnd.dvb.service' => 'svc',
'application/vnd.dynageo' => 'geo',
'application/vnd.ecowin.chart' => 'mag',
'application/vnd.enliven' => 'nml',
'application/vnd.epson.esf' => 'esf',
'application/vnd.epson.msf' => 'msf',
'application/vnd.epson.quickanime' => 'qam',
'application/vnd.epson.salt' => 'slt',
'application/vnd.epson.ssf' => 'ssf',
'application/vnd.eszigno3+xml' => 'es3',
'application/vnd.ezpix-album' => 'ez2',
'application/vnd.ezpix-package' => 'ez3',
'application/vnd.fdf' => 'fdf',
'application/vnd.fdsn.mseed' => 'mseed',
'application/vnd.fdsn.seed' => 'seed',
'application/vnd.flographit' => 'gph',
'application/vnd.fluxtime.clip' => 'ftc',
'application/vnd.framemaker' => 'fm',
'application/vnd.frogans.fnc' => 'fnc',
'application/vnd.frogans.ltf' => 'ltf',
'application/vnd.fsc.weblaunch' => 'fsc',
'application/vnd.fujitsu.oasys' => 'oas',
'application/vnd.fujitsu.oasys2' => 'oa2',
'application/vnd.fujitsu.oasys3' => 'oa3',
'application/vnd.fujitsu.oasysgp' => 'fg5',
'application/vnd.fujitsu.oasysprs' => 'bh2',
'application/vnd.fujixerox.ddd' => 'ddd',
'application/vnd.fujixerox.docuworks' => 'xdw',
'application/vnd.fujixerox.docuworks.binder' => 'xbd',
'application/vnd.fuzzysheet' => 'fzs',
'application/vnd.genomatix.tuxedo' => 'txd',
'application/vnd.geogebra.file' => 'ggb',
'application/vnd.geogebra.tool' => 'ggt',
'application/vnd.geometry-explorer' => 'gex',
'application/vnd.geonext' => 'gxt',
'application/vnd.geoplan' => 'g2w',
'application/vnd.geospace' => 'g3w',
'application/vnd.gmx' => 'gmx',
'application/vnd.google-earth.kml+xml' => 'kml',
'application/vnd.google-earth.kmz' => 'kmz',
'application/vnd.grafeq' => 'gqf',
'application/vnd.groove-account' => 'gac',
'application/vnd.groove-help' => 'ghf',
'application/vnd.groove-identity-message' => 'gim',
'application/vnd.groove-injector' => 'grv',
'application/vnd.groove-tool-message' => 'gtm',
'application/vnd.groove-tool-template' => 'tpl',
'application/vnd.groove-vcard' => 'vcg',
'application/vnd.hal+xml' => 'hal',
'application/vnd.handheld-entertainment+xml' => 'zmm',
'application/vnd.hbci' => 'hbci',
'application/vnd.hhe.lesson-player' => 'les',
'application/vnd.hp-hpgl' => 'hpgl',
'application/vnd.hp-hpid' => 'hpid',
'application/vnd.hp-hps' => 'hps',
'application/vnd.hp-jlyt' => 'jlt',
'application/vnd.hp-pcl' => 'pcl',
'application/vnd.hp-pclxl' => 'pclxl',
'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
'application/vnd.ibm.minipay' => 'mpy',
'application/vnd.ibm.modcap' => 'afp',
'application/vnd.ibm.rights-management' => 'irm',
'application/vnd.ibm.secure-container' => 'sc',
'application/vnd.iccprofile' => 'icc',
'application/vnd.igloader' => 'igl',
'application/vnd.immervision-ivp' => 'ivp',
'application/vnd.immervision-ivu' => 'ivu',
'application/vnd.insors.igm' => 'igm',
'application/vnd.intercon.formnet' => 'xpw',
'application/vnd.intergeo' => 'i2g',
'application/vnd.intu.qbo' => 'qbo',
'application/vnd.intu.qfx' => 'qfx',
'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
'application/vnd.irepository.package+xml' => 'irp',
'application/vnd.is-xpr' => 'xpr',
'application/vnd.isac.fcs' => 'fcs',
'application/vnd.jam' => 'jam',
'application/vnd.jcp.javame.midlet-rms' => 'rms',
'application/vnd.jisp' => 'jisp',
'application/vnd.joost.joda-archive' => 'joda',
'application/vnd.kahootz' => 'ktz',
'application/vnd.kde.karbon' => 'karbon',
'application/vnd.kde.kchart' => 'chrt',
'application/vnd.kde.kformula' => 'kfo',
'application/vnd.kde.kivio' => 'flw',
'application/vnd.kde.kontour' => 'kon',
'application/vnd.kde.kpresenter' => 'kpr',
'application/vnd.kde.kspread' => 'ksp',
'application/vnd.kde.kword' => 'kwd',
'application/vnd.kenameaapp' => 'htke',
'application/vnd.kidspiration' => 'kia',
'application/vnd.kinar' => 'kne',
'application/vnd.koan' => 'skp',
'application/vnd.kodak-descriptor' => 'sse',
'application/vnd.las.las+xml' => 'lasxml',
'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
'application/vnd.lotus-1-2-3' => '123',
'application/vnd.lotus-approach' => 'apr',
'application/vnd.lotus-freelance' => 'pre',
'application/vnd.lotus-notes' => 'nsf',
'application/vnd.lotus-organizer' => 'org',
'application/vnd.lotus-screencam' => 'scm',
'application/vnd.lotus-wordpro' => 'lwp',
'application/vnd.macports.portpkg' => 'portpkg',
'application/vnd.mcd' => 'mcd',
'application/vnd.medcalcdata' => 'mc1',
'application/vnd.mediastation.cdkey' => 'cdkey',
'application/vnd.mfer' => 'mwf',
'application/vnd.mfmp' => 'mfm',
'application/vnd.micrografx.flo' => 'flo',
'application/vnd.micrografx.igx' => 'igx',
'application/vnd.mif' => 'mif',
'application/vnd.mobius.daf' => 'daf',
'application/vnd.mobius.dis' => 'dis',
'application/vnd.mobius.mbk' => 'mbk',
'application/vnd.mobius.mqy' => 'mqy',
'application/vnd.mobius.msl' => 'msl',
'application/vnd.mobius.plc' => 'plc',
'application/vnd.mobius.txf' => 'txf',
'application/vnd.mophun.application' => 'mpn',
'application/vnd.mophun.certificate' => 'mpc',
'application/vnd.mozilla.xul+xml' => 'xul',
'application/vnd.ms-artgalry' => 'cil',
'application/vnd.ms-cab-compressed' => 'cab',
'application/vnd.ms-excel' => 'xls',
'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
'application/vnd.ms-fontobject' => 'eot',
'application/vnd.ms-htmlhelp' => 'chm',
'application/vnd.ms-ims' => 'ims',
'application/vnd.ms-lrm' => 'lrm',
'application/vnd.ms-officetheme' => 'thmx',
'application/vnd.ms-pki.seccat' => 'cat',
'application/vnd.ms-pki.stl' => 'stl',
'application/vnd.ms-powerpoint' => 'ppt',
'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
'application/vnd.ms-project' => 'mpp',
'application/vnd.ms-word.document.macroenabled.12' => 'docm',
'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
'application/vnd.ms-works' => 'wps',
'application/vnd.ms-wpl' => 'wpl',
'application/vnd.ms-xpsdocument' => 'xps',
'application/vnd.mseq' => 'mseq',
'application/vnd.musician' => 'mus',
'application/vnd.muvee.style' => 'msty',
'application/vnd.mynfc' => 'taglet',
'application/vnd.neurolanguage.nlu' => 'nlu',
'application/vnd.nitf' => 'ntf',
'application/vnd.noblenet-directory' => 'nnd',
'application/vnd.noblenet-sealer' => 'nns',
'application/vnd.noblenet-web' => 'nnw',
'application/vnd.nokia.n-gage.data' => 'ngdat',
'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
'application/vnd.nokia.radio-preset' => 'rpst',
'application/vnd.nokia.radio-presets' => 'rpss',
'application/vnd.novadigm.edm' => 'edm',
'application/vnd.novadigm.edx' => 'edx',
'application/vnd.novadigm.ext' => 'ext',
'application/vnd.oasis.opendocument.chart' => 'odc',
'application/vnd.oasis.opendocument.chart-template' => 'otc',
'application/vnd.oasis.opendocument.database' => 'odb',
'application/vnd.oasis.opendocument.formula' => 'odf',
'application/vnd.oasis.opendocument.formula-template' => 'odft',
'application/vnd.oasis.opendocument.graphics' => 'odg',
'application/vnd.oasis.opendocument.graphics-template' => 'otg',
'application/vnd.oasis.opendocument.image' => 'odi',
'application/vnd.oasis.opendocument.image-template' => 'oti',
'application/vnd.oasis.opendocument.presentation' => 'odp',
'application/vnd.oasis.opendocument.presentation-template' => 'otp',
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
'application/vnd.oasis.opendocument.text' => 'odt',
'application/vnd.oasis.opendocument.text-master' => 'odm',
'application/vnd.oasis.opendocument.text-template' => 'ott',
'application/vnd.oasis.opendocument.text-web' => 'oth',
'application/vnd.olpc-sugar' => 'xo',
'application/vnd.oma.dd2+xml' => 'dd2',
'application/vnd.openofficeorg.extension' => 'oxt',
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
'application/vnd.osgeo.mapguide.package' => 'mgp',
'application/vnd.osgi.dp' => 'dp',
'application/vnd.osgi.subsystem' => 'esa',
'application/vnd.palm' => 'pdb',
'application/vnd.pawaafile' => 'paw',
'application/vnd.pg.format' => 'str',
'application/vnd.pg.osasli' => 'ei6',
'application/vnd.picsel' => 'efif',
'application/vnd.pmi.widget' => 'wg',
'application/vnd.pocketlearn' => 'plf',
'application/vnd.powerbuilder6' => 'pbd',
'application/vnd.previewsystems.box' => 'box',
'application/vnd.proteus.magazine' => 'mgz',
'application/vnd.publishare-delta-tree' => 'qps',
'application/vnd.pvi.ptid1' => 'ptid',
'application/vnd.quark.quarkxpress' => 'qxd',
'application/vnd.realvnc.bed' => 'bed',
'application/vnd.recordare.musicxml' => 'mxl',
'application/vnd.recordare.musicxml+xml' => 'musicxml',
'application/vnd.rig.cryptonote' => 'cryptonote',
'application/vnd.rim.cod' => 'cod',
'application/vnd.rn-realmedia' => 'rm',
'application/vnd.rn-realmedia-vbr' => 'rmvb',
'application/vnd.route66.link66+xml' => 'link66',
'application/vnd.sailingtracker.track' => 'st',
'application/vnd.seemail' => 'see',
'application/vnd.sema' => 'sema',
'application/vnd.semd' => 'semd',
'application/vnd.semf' => 'semf',
'application/vnd.shana.informed.formdata' => 'ifm',
'application/vnd.shana.informed.formtemplate' => 'itp',
'application/vnd.shana.informed.interchange' => 'iif',
'application/vnd.shana.informed.package' => 'ipk',
'application/vnd.simtech-mindmapper' => 'twd',
'application/vnd.smaf' => 'mmf',
'application/vnd.smart.teacher' => 'teacher',
'application/vnd.solent.sdkm+xml' => 'sdkm',
'application/vnd.spotfire.dxp' => 'dxp',
'application/vnd.spotfire.sfs' => 'sfs',
'application/vnd.stardivision.calc' => 'sdc',
'application/vnd.stardivision.draw' => 'sda',
'application/vnd.stardivision.impress' => 'sdd',
'application/vnd.stardivision.math' => 'smf',
'application/vnd.stardivision.writer' => 'sdw',
'application/vnd.stardivision.writer-global' => 'sgl',
'application/vnd.stepmania.package' => 'smzip',
'application/vnd.stepmania.stepchart' => 'sm',
'application/vnd.sun.xml.calc' => 'sxc',
'application/vnd.sun.xml.calc.template' => 'stc',
'application/vnd.sun.xml.draw' => 'sxd',
'application/vnd.sun.xml.draw.template' => 'std',
'application/vnd.sun.xml.impress' => 'sxi',
'application/vnd.sun.xml.impress.template' => 'sti',
'application/vnd.sun.xml.math' => 'sxm',
'application/vnd.sun.xml.writer' => 'sxw',
'application/vnd.sun.xml.writer.global' => 'sxg',
'application/vnd.sun.xml.writer.template' => 'stw',
'application/vnd.sus-calendar' => 'sus',
'application/vnd.svd' => 'svd',
'application/vnd.symbian.install' => 'sis',
'application/vnd.syncml+xml' => 'xsm',
'application/vnd.syncml.dm+wbxml' => 'bdm',
'application/vnd.syncml.dm+xml' => 'xdm',
'application/vnd.tao.intent-module-archive' => 'tao',
'application/vnd.tcpdump.pcap' => 'pcap',
'application/vnd.tmobile-livetv' => 'tmo',
'application/vnd.trid.tpt' => 'tpt',
'application/vnd.triscape.mxs' => 'mxs',
'application/vnd.trueapp' => 'tra',
'application/vnd.ufdl' => 'ufd',
'application/vnd.uiq.theme' => 'utz',
'application/vnd.umajin' => 'umj',
'application/vnd.unity' => 'unityweb',
'application/vnd.uoml+xml' => 'uoml',
'application/vnd.vcx' => 'vcx',
'application/vnd.visio' => 'vsd',
'application/vnd.visionary' => 'vis',
'application/vnd.vsf' => 'vsf',
'application/vnd.wap.wbxml' => 'wbxml',
'application/vnd.wap.wmlc' => 'wmlc',
'application/vnd.wap.wmlscriptc' => 'wmlsc',
'application/vnd.webturbo' => 'wtb',
'application/vnd.wolfram.player' => 'nbp',
'application/vnd.wordperfect' => 'wpd',
'application/vnd.wqd' => 'wqd',
'application/vnd.wt.stf' => 'stf',
'application/vnd.xara' => 'xar',
'application/vnd.xfdl' => 'xfdl',
'application/vnd.yamaha.hv-dic' => 'hvd',
'application/vnd.yamaha.hv-script' => 'hvs',
'application/vnd.yamaha.hv-voice' => 'hvp',
'application/vnd.yamaha.openscoreformat' => 'osf',
'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
'application/vnd.yamaha.smaf-audio' => 'saf',
'application/vnd.yamaha.smaf-phrase' => 'spf',
'application/vnd.yellowriver-custom-menu' => 'cmp',
'application/vnd.zul' => 'zir',
'application/vnd.zzazz.deck+xml' => 'zaz',
'application/voicexml+xml' => 'vxml',
'application/widget' => 'wgt',
'application/winhlp' => 'hlp',
'application/wsdl+xml' => 'wsdl',
'application/wspolicy+xml' => 'wspolicy',
'application/x-7z-compressed' => '7z',
'application/x-abiword' => 'abw',
'application/x-ace-compressed' => 'ace',
'application/x-apple-diskimage' => 'dmg',
'application/x-authorware-bin' => 'aab',
'application/x-authorware-map' => 'aam',
'application/x-authorware-seg' => 'aas',
'application/x-bcpio' => 'bcpio',
'application/x-bittorrent' => 'torrent',
'application/x-blorb' => 'blb',
'application/x-bzip' => 'bz',
'application/x-bzip2' => 'bz2',
'application/x-cbr' => 'cbr',
'application/x-cdlink' => 'vcd',
'application/x-cfs-compressed' => 'cfs',
'application/x-chat' => 'chat',
'application/x-chess-pgn' => 'pgn',
'application/x-conference' => 'nsc',
'application/x-cpio' => 'cpio',
'application/x-csh' => 'csh',
'application/x-debian-package' => 'deb',
'application/x-dgc-compressed' => 'dgc',
'application/x-director' => 'dir',
'application/x-doom' => 'wad',
'application/x-dtbncx+xml' => 'ncx',
'application/x-dtbook+xml' => 'dtb',
'application/x-dtbresource+xml' => 'res',
'application/x-dvi' => 'dvi',
'application/x-envoy' => 'evy',
'application/x-eva' => 'eva',
'application/x-font-bdf' => 'bdf',
'application/x-font-ghostscript' => 'gsf',
'application/x-font-linux-psf' => 'psf',
'application/x-font-otf' => 'otf',
'application/x-font-pcf' => 'pcf',
'application/x-font-snf' => 'snf',
'application/x-font-ttf' => 'ttf',
'application/x-font-type1' => 'pfa',
'application/x-font-woff' => 'woff',
'application/x-freearc' => 'arc',
'application/x-futuresplash' => 'spl',
'application/x-gca-compressed' => 'gca',
'application/x-glulx' => 'ulx',
'application/x-gnumeric' => 'gnumeric',
'application/x-gramps-xml' => 'gramps',
'application/x-gtar' => 'gtar',
'application/x-hdf' => 'hdf',
'application/x-install-instructions' => 'install',
'application/x-iso9660-image' => 'iso',
'application/x-java-jnlp-file' => 'jnlp',
'application/x-latex' => 'latex',
'application/x-lzh-compressed' => 'lzh',
'application/x-mie' => 'mie',
'application/x-mobipocket-ebook' => 'prc',
'application/x-ms-application' => 'application',
'application/x-ms-shortcut' => 'lnk',
'application/x-ms-wmd' => 'wmd',
'application/x-ms-wmz' => 'wmz',
'application/x-ms-xbap' => 'xbap',
'application/x-msaccess' => 'mdb',
'application/x-msbinder' => 'obd',
'application/x-mscardfile' => 'crd',
'application/x-msclip' => 'clp',
'application/x-msdownload' => 'exe',
'application/x-msmediaview' => 'mvb',
'application/x-msmetafile' => 'wmf',
'application/x-msmoney' => 'mny',
'application/x-mspublisher' => 'pub',
'application/x-msschedule' => 'scd',
'application/x-msterminal' => 'trm',
'application/x-mswrite' => 'wri',
'application/x-netcdf' => 'nc',
'application/x-nzb' => 'nzb',
'application/x-pkcs12' => 'p12',
'application/x-pkcs7-certificates' => 'p7b',
'application/x-pkcs7-certreqresp' => 'p7r',
'application/x-rar-compressed' => 'rar',
'application/x-rar' => 'rar',
'application/x-research-info-systems' => 'ris',
'application/x-sh' => 'sh',
'application/x-shar' => 'shar',
'application/x-shockwave-flash' => 'swf',
'application/x-silverlight-app' => 'xap',
'application/x-sql' => 'sql',
'application/x-stuffit' => 'sit',
'application/x-stuffitx' => 'sitx',
'application/x-subrip' => 'srt',
'application/x-sv4cpio' => 'sv4cpio',
'application/x-sv4crc' => 'sv4crc',
'application/x-t3vm-image' => 't3',
'application/x-tads' => 'gam',
'application/x-tar' => 'tar',
'application/x-tcl' => 'tcl',
'application/x-tex' => 'tex',
'application/x-tex-tfm' => 'tfm',
'application/x-texinfo' => 'texinfo',
'application/x-tgif' => 'obj',
'application/x-ustar' => 'ustar',
'application/x-wais-source' => 'src',
'application/x-x509-ca-cert' => 'der',
'application/x-xfig' => 'fig',
'application/x-xliff+xml' => 'xlf',
'application/x-xpinstall' => 'xpi',
'application/x-xz' => 'xz',
'application/x-zmachine' => 'z1',
'application/xaml+xml' => 'xaml',
'application/xcap-diff+xml' => 'xdf',
'application/xenc+xml' => 'xenc',
'application/xhtml+xml' => 'xhtml',
'application/xml' => 'xml',
'application/xml-dtd' => 'dtd',
'application/xop+xml' => 'xop',
'application/xproc+xml' => 'xpl',
'application/xslt+xml' => 'xslt',
'application/xspf+xml' => 'xspf',
'application/xv+xml' => 'mxml',
'application/yang' => 'yang',
'application/yin+xml' => 'yin',
'application/zip' => 'zip',
'audio/adpcm' => 'adp',
'audio/basic' => 'au',
'audio/midi' => 'mid',
'audio/mp4' => 'mp4a',
'audio/mpeg' => 'mpga',
'audio/ogg' => 'oga',
'audio/s3m' => 's3m',
'audio/silk' => 'sil',
'audio/vnd.dece.audio' => 'uva',
'audio/vnd.digital-winds' => 'eol',
'audio/vnd.dra' => 'dra',
'audio/vnd.dts' => 'dts',
'audio/vnd.dts.hd' => 'dtshd',
'audio/vnd.lucent.voice' => 'lvp',
'audio/vnd.ms-playready.media.pya' => 'pya',
'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
'audio/vnd.rip' => 'rip',
'audio/webm' => 'weba',
'audio/x-aac' => 'aac',
'audio/x-aiff' => 'aif',
'audio/x-caf' => 'caf',
'audio/x-flac' => 'flac',
'audio/x-matroska' => 'mka',
'audio/x-mpegurl' => 'm3u',
'audio/x-ms-wax' => 'wax',
'audio/x-ms-wma' => 'wma',
'audio/x-pn-realaudio' => 'ram',
'audio/x-pn-realaudio-plugin' => 'rmp',
'audio/x-wav' => 'wav',
'audio/xm' => 'xm',
'chemical/x-cdx' => 'cdx',
'chemical/x-cif' => 'cif',
'chemical/x-cmdf' => 'cmdf',
'chemical/x-cml' => 'cml',
'chemical/x-csml' => 'csml',
'chemical/x-xyz' => 'xyz',
'image/bmp' => 'bmp',
'image/x-ms-bmp' => 'bmp',
'image/cgm' => 'cgm',
'image/g3fax' => 'g3',
'image/gif' => 'gif',
'image/ief' => 'ief',
'image/jpeg' => 'jpeg',
'image/pjpeg' => 'jpeg',
'image/ktx' => 'ktx',
'image/png' => 'png',
'image/prs.btif' => 'btif',
'image/sgi' => 'sgi',
'image/svg+xml' => 'svg',
'image/tiff' => 'tiff',
'image/vnd.adobe.photoshop' => 'psd',
'image/vnd.dece.graphic' => 'uvi',
'image/vnd.dvb.subtitle' => 'sub',
'image/vnd.djvu' => 'djvu',
'image/vnd.dwg' => 'dwg',
'image/vnd.dxf' => 'dxf',
'image/vnd.fastbidsheet' => 'fbs',
'image/vnd.fpx' => 'fpx',
'image/vnd.fst' => 'fst',
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
'image/vnd.ms-modi' => 'mdi',
'image/vnd.ms-photo' => 'wdp',
'image/vnd.net-fpx' => 'npx',
'image/vnd.wap.wbmp' => 'wbmp',
'image/vnd.xiff' => 'xif',
'image/webp' => 'webp',
'image/x-3ds' => '3ds',
'image/x-cmu-raster' => 'ras',
'image/x-cmx' => 'cmx',
'image/x-freehand' => 'fh',
'image/x-icon' => 'ico',
'image/x-mrsid-image' => 'sid',
'image/x-pcx' => 'pcx',
'image/x-pict' => 'pic',
'image/x-portable-anymap' => 'pnm',
'image/x-portable-bitmap' => 'pbm',
'image/x-portable-graymap' => 'pgm',
'image/x-portable-pixmap' => 'ppm',
'image/x-rgb' => 'rgb',
'image/x-tga' => 'tga',
'image/x-xbitmap' => 'xbm',
'image/x-xpixmap' => 'xpm',
'image/x-xwindowdump' => 'xwd',
'message/rfc822' => 'eml',
'model/iges' => 'igs',
'model/mesh' => 'msh',
'model/vnd.collada+xml' => 'dae',
'model/vnd.dwf' => 'dwf',
'model/vnd.gdl' => 'gdl',
'model/vnd.gtw' => 'gtw',
'model/vnd.mts' => 'mts',
'model/vnd.vtu' => 'vtu',
'model/vrml' => 'wrl',
'model/x3d+binary' => 'x3db',
'model/x3d+vrml' => 'x3dv',
'model/x3d+xml' => 'x3d',
'text/cache-manifest' => 'appcache',
'text/calendar' => 'ics',
'text/css' => 'css',
'text/csv' => 'csv',
'text/html' => 'html',
'text/n3' => 'n3',
'text/plain' => 'txt',
'text/prs.lines.tag' => 'dsc',
'text/richtext' => 'rtx',
'text/rtf' => 'rtf',
'text/sgml' => 'sgml',
'text/tab-separated-values' => 'tsv',
'text/troff' => 't',
'text/turtle' => 'ttl',
'text/uri-list' => 'uri',
'text/vcard' => 'vcard',
'text/vnd.curl' => 'curl',
'text/vnd.curl.dcurl' => 'dcurl',
'text/vnd.curl.scurl' => 'scurl',
'text/vnd.curl.mcurl' => 'mcurl',
'text/vnd.dvb.subtitle' => 'sub',
'text/vnd.fly' => 'fly',
'text/vnd.fmi.flexstor' => 'flx',
'text/vnd.graphviz' => 'gv',
'text/vnd.in3d.3dml' => '3dml',
'text/vnd.in3d.spot' => 'spot',
'text/vnd.sun.j2me.app-descriptor' => 'jad',
'text/vnd.wap.wml' => 'wml',
'text/vnd.wap.wmlscript' => 'wmls',
'text/vtt' => 'vtt',
'text/x-asm' => 's',
'text/x-c' => 'c',
'text/x-fortran' => 'f',
'text/x-pascal' => 'p',
'text/x-java-source' => 'java',
'text/x-opml' => 'opml',
'text/x-nfo' => 'nfo',
'text/x-setext' => 'etx',
'text/x-sfv' => 'sfv',
'text/x-uuencode' => 'uu',
'text/x-vcalendar' => 'vcs',
'text/x-vcard' => 'vcf',
'video/3gpp' => '3gp',
'video/3gpp2' => '3g2',
'video/h261' => 'h261',
'video/h263' => 'h263',
'video/h264' => 'h264',
'video/jpeg' => 'jpgv',
'video/jpm' => 'jpm',
'video/mj2' => 'mj2',
'video/mp4' => 'mp4',
'video/mpeg' => 'mpeg',
'video/ogg' => 'ogv',
'video/quicktime' => 'qt',
'video/vnd.dece.hd' => 'uvh',
'video/vnd.dece.mobile' => 'uvm',
'video/vnd.dece.pd' => 'uvp',
'video/vnd.dece.sd' => 'uvs',
'video/vnd.dece.video' => 'uvv',
'video/vnd.dvb.file' => 'dvb',
'video/vnd.fvt' => 'fvt',
'video/vnd.mpegurl' => 'mxu',
'video/vnd.ms-playready.media.pyv' => 'pyv',
'video/vnd.uvvu.mp4' => 'uvu',
'video/vnd.vivo' => 'viv',
'video/webm' => 'webm',
'video/x-f4v' => 'f4v',
'video/x-fli' => 'fli',
'video/x-flv' => 'flv',
'video/x-m4v' => 'm4v',
'video/x-matroska' => 'mkv',
'video/x-mng' => 'mng',
'video/x-ms-asf' => 'asf',
'video/x-ms-vob' => 'vob',
'video/x-ms-wm' => 'wm',
'video/x-ms-wmv' => 'wmv',
'video/x-ms-wmx' => 'wmx',
'video/x-ms-wvx' => 'wvx',
'video/x-msvideo' => 'avi',
'video/x-sgi-movie' => 'movie',
'video/x-smv' => 'smv',
'x-conference/x-cooltalk' => 'ice',
];
/**
* Original file name.
*
* @var string $originalName
*/
private $originalName;
/**
* Mime type of the file.
*
* @var string $mimeType
*/
private $mimeType;
/**
* File size in kilobyte.
*
* @var int|null $size
*/
private $size;
/**
* File upload error.
*
* @var int $error
*/
private $error;
/**
* HTTP File instantiator.
*
* @param $path
* @param $originalName
* @param null $mimeType
* @param null $size
* @param null $error
*/
public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null)
{
$this->originalName = $this->getName($originalName);
$this->mimeType = $mimeType ?: 'application/octet-stream';
$this->size = $size;
$this->error = $error ?: UPLOAD_ERR_OK;
parent::__construct($path);
}
/**
* @taken from \Symfony\Component\HttpFoundation\File\File
*
* Returns locale independent base name of the given path.
*
* @param string $name The new file name
*
* @return string containing
*/
public function getName($name)
{
$originalName = str_replace('\\', '/', $name);
$pos = strrpos($originalName, '/');
$originalName = false === $pos ? $originalName : substr($originalName, $pos + 1);
return $originalName;
}
/**
* Get the file upload error.
*
* @return int
*/
public function getError()
{
return $this->error;
}
/**
* Returns whether the file was uploaded successfully.
*
* @return bool True if the file has been uploaded with HTTP and no error occurred
*/
public function isValid()
{
$isOk = UPLOAD_ERR_OK === $this->getError();
return $isOk && is_uploaded_file($this->getPathname());
}
/**
* Returns the original file extension.
*
* It is extracted from the original file name that was uploaded.
* Then it should not be considered as a safe value.
*
* @return string The extension
*/
public function getClientOriginalExtension()
{
return pathinfo($this->originalName, PATHINFO_EXTENSION);
}
/**
* Take an educated guess of the file's extension.
*
* @return mixed|null
*/
public function guessExtension()
{
$type = $this->getMimeType();
return isset($this->defaultExtensions[$type]) ? $this->defaultExtensions[$type] : null;
}
/**
* Take an educated guess of the file's mime type.
*
* @return string
*/
public function getMimeType()
{
$path = $this->getPathname();
if(!function_exists('wp_check_filetype_and_ext')) {
require_once ABSPATH .'wp-admin/includes/file.php';
}
$typeInfo = wp_check_filetype_and_ext($path, $this->originalName);
return $typeInfo['type'];
}
/**
* Get original HTTP file array
*
* @return array
*/
public function toArray()
{
return [
'name' => $this->originalName,
'type' => $this->mimeType,
'tmp_name' => $this->getPathname(),
'error' => $this->error,
'size' => $this->size
];
}
/**
* Returns the contents of the file.
*
* @return string the contents of the file
*
* @throws \RuntimeException
*/
public function getContents()
{
$level = error_reporting(0);
$content = file_get_contents($this->getPathname());
error_reporting($level);
if (false === $content) {
$error = error_get_last();
throw new \RuntimeException($error['message']); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
return $content;
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace FluentMail\Includes\Request;
trait FileHandler
{
/**
* Prepares HTTP files for Request
*
* @param array $files
*
* @return array
*/
public function prepareFiles($files = [])
{
foreach ($files as $key => &$file) {
$file = $this->convertFileInformation($file);
}
return $files;
}
/**
* @taken from \Symfony\Component\HttpFoundation\FileBag
*
* Converts uploaded files to UploadedFile instances.
*
* @param array|File $file A (multi-dimensional) array of uploaded file information
*
* @return File[]|File|null A (multi-dimensional) array of File instances
*/
protected function convertFileInformation($file)
{
$fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
if ($file instanceof File) {
return $file;
}
$file = $this->fixPhpFilesArray($file);
if (is_array($file)) {
$keys = array_keys($file);
sort($keys);
if ($keys == $fileKeys) {
if (UPLOAD_ERR_NO_FILE == $file['error']) {
$file = null;
} else {
$file = new File($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
}
} else {
$file = array_map(array($this, 'convertFileInformation'), $file);
if (array_keys($keys) === $keys) {
$file = array_filter($file);
}
}
}
return $file;
}
/**
* @taken from \Symfony\Component\HttpFoundation\FileBag
*
* Fixes a malformed PHP $_FILES array.
*
* PHP has a bug that the format of the $_FILES array differs, depending on
* whether the uploaded file fields had normal field names or array-like
* field names ("normal" vs. "parent[child]").
*
* This method fixes the array to look like the "normal" $_FILES array.
*
* It's safe to pass an already converted array, in which case this method
* just returns the original array unmodified.
*
* @return array
*/
protected function fixPhpFilesArray($data)
{
$fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
if (! is_array($data)) {
return $data;
}
$keys = array_keys($data);
sort($keys);
if ($fileKeys != $keys || ! isset($data['name']) || ! is_array($data['name'])) {
return $data;
}
$files = $data;
foreach ($fileKeys as $k) {
unset($files[$k]);
}
foreach ($data['name'] as $key => $name) {
$files[$key] = $this->fixPhpFilesArray(array(
'error' => $data['error'][$key],
'name' => $name,
'type' => $data['type'][$key],
'tmp_name' => $data['tmp_name'][$key],
'size' => $data['size'][$key],
));
}
return $files;
}
}

View File

@@ -0,0 +1,236 @@
<?php
namespace FluentMail\Includes\Request;
use FluentMail\Includes\Support\Arr;
class Request
{
use FileHandler, Cleaner;
protected $app = null;
protected $headers = array();
protected $server = array();
protected $cookie = array();
protected $json = array();
protected $get = array();
protected $post = array();
protected $files = array();
protected $request = array();
public function __construct($app, $get, $post, $files)
{
$this->app = $app;
$this->server = $_SERVER;
$this->cookie = $_COOKIE;
$this->files = $this->prepareFiles($files);
$this->request = array_merge(
$this->get = $this->clean($get),
$this->post = $this->clean($post)
);
}
/**
* Variable exists
* @param string $key
* @return bool
*/
public function exists($key)
{
return Arr::has($this->request, $key);
}
/**
* Variable exists and has truthy value
* @param string $key
* @return bool
*/
public function has($key)
{
return $this->exists($key) && !empty(Arr::get($this->request, $key));
}
public function set($key, $value)
{
Arr::set($this->request, $key, $value);
return $this;
}
public function all()
{
return $this->get();
}
public function get($key = null, $default = null)
{
return Arr::get($this->request, $key, $default);
}
/**
* Get the files from the request.
*
* @return array
*/
public function files()
{
return $this->files;
}
public function query($key = null, $default = null)
{
return $key ? Arr::get($this->get, $key, $default) : $this->get;
}
public function post($key = null, $default = null)
{
return $key ? Arr::get($this->post, $key, $default) : $this->post;
}
public function only($keys)
{
return Arr::only($this->request, $keys);
}
public function except($args)
{
return Arr::except($this->request, $args);
}
public function merge(array $data = [])
{
$this->request = array_replace($this->request, $data);
return $this;
}
/**
* Get user ip address
* @return string
*/
public function getIp()
{
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $this->server('HTTP_CLIENT_IP');
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $this->server('HTTP_X_FORWARDED_FOR');
} else {
$ip = $this->server('REMOTE_ADDR');
}
return $ip;
}
public function server($key = null, $default = null)
{
return $key ? Arr::get($this->server, $key, $default) : $this->server;
}
public function header($key = null, $default = null)
{
if (!$this->headers) {
$this->headers = $this->setHeaders();
}
return $key ? Arr::get($this->headers, $key, $default) : $this->headers;
}
public function method()
{
return $this->server('REQUEST_METHOD');
}
public function cookie($key = null, $default = null)
{
return $key ? Arr::get($this->cookie, $key, $default) : $this->cookie;
}
/**
* Taken and modified from Symfony
*/
public function setHeaders()
{
$headers = array();
$parameters = $this->server;
$contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
foreach ($parameters as $key => $value) {
if (0 === strpos($key, 'HTTP_')) {
$headers[substr($key, 5)] = $value;
} // CONTENT_* are not prefixed with HTTP_
elseif (isset($contentHeaders[$key])) {
$headers[$key] = $value;
}
}
if (isset($parameters['PHP_AUTH_USER'])) {
$headers['PHP_AUTH_USER'] = $parameters['PHP_AUTH_USER'];
$headers['PHP_AUTH_PW'] = isset($parameters['PHP_AUTH_PW']) ? $parameters['PHP_AUTH_PW'] : '';
} else {
/*
* php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
* For this workaround to work, add these lines to your .htaccess file:
* RewriteCond %{HTTP:Authorization} ^(.+)$
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
*
* A sample .htaccess file:
* RewriteEngine On
* RewriteCond %{HTTP:Authorization} ^(.+)$
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteRule ^(.*)$ app.php [QSA,L]
*/
$authorizationHeader = null;
if (isset($parameters['HTTP_AUTHORIZATION'])) {
$authorizationHeader = $parameters['HTTP_AUTHORIZATION'];
} elseif (isset($parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
$authorizationHeader = $parameters['REDIRECT_HTTP_AUTHORIZATION'];
}
if (null !== $authorizationHeader) {
if (0 === stripos($authorizationHeader, 'basic ')) {
// Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
$exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2);
if (count($exploded) == 2) {
list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
}
} elseif (empty($parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) {
// In some circumstances PHP_AUTH_DIGEST needs to be set
$headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
$parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
} elseif (0 === stripos($authorizationHeader, 'bearer ')) {
/*
* XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables,
* I'll just set $headers['AUTHORIZATION'] here.
* http://php.net/manual/en/reserved.variables.server.php
*/
$headers['AUTHORIZATION'] = $authorizationHeader;
}
}
}
if (isset($headers['AUTHORIZATION'])) {
return $headers;
}
// PHP_AUTH_USER/PHP_AUTH_PW
if (isset($headers['PHP_AUTH_USER'])) {
$headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
} elseif (isset($headers['PHP_AUTH_DIGEST'])) {
$headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST'];
}
return $headers;
}
/**
* Get an input element from the request.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this->get($key);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace FluentMail\Includes\Response;
class Response
{
protected $app = null;
public function __construct($app)
{
$this->app = $app;
}
public function json($data = null, $code = 200)
{
wp_send_json($data, $code);
}
public function send($data = null, $code = 200)
{
wp_send_json($data, $code);
}
public function sendSuccess($data = null, $code = null)
{
wp_send_json_success($data, $code);
}
public function sendError($data = null, $code = null)
{
wp_send_json_error($data, $code);
}
}

View File

@@ -0,0 +1,417 @@
<?php
namespace FluentMail\Includes\Support;
use Closure;
use ArrayAccess;
use FluentMail\Includes\Support\Collection;
use FluentMail\Includes\Support\MacroableTrait;
class Arr {
use MacroableTrait;
/**
* Add an element to an array using "dot" notation if it doesn't exist.
*
* @param array $array
* @param string $key
* @param mixed $value
* @return array
*/
public static function add($array, $key, $value)
{
if (is_null(static::get($array, $key)))
{
static::set($array, $key, $value);
}
return $array;
}
/**
* Build a new array using a callback.
*
* @param array $array
* @param \Closure $callback
* @return array
*/
public static function build($array, Closure $callback)
{
$results = array();
foreach ($array as $key => $value)
{
list($innerKey, $innerValue) = call_user_func($callback, $key, $value);
$results[$innerKey] = $innerValue;
}
return $results;
}
/**
* Divide an array into two arrays. One with keys and the other with values.
*
* @param array $array
* @return array
*/
public static function divide($array)
{
return array(array_keys($array), array_values($array));
}
/**
* Flatten a multi-dimensional associative array with dots.
*
* @param array $array
* @param string $prepend
* @return array
*/
public static function dot($array, $prepend = '')
{
$results = array();
foreach ($array as $key => $value)
{
if (is_array($value))
{
$results = array_merge($results, static::dot($value, $prepend.$key.'.'));
}
else
{
$results[$prepend.$key] = $value;
}
}
return $results;
}
/**
* Get all of the given array except for a specified array of items.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function except($array, $keys)
{
return array_diff_key($array, array_flip((array) $keys));
}
/**
* Fetch a flattened array of a nested array element.
*
* @param array $array
* @param string $key
* @return array
*/
public static function fetch($array, $key)
{
foreach (explode('.', $key) as $segment)
{
$results = array();
foreach ($array as $value)
{
if (array_key_exists($segment, $value = (array) $value))
{
$results[] = $value[$segment];
}
}
$array = array_values($results);
}
return array_values($results);
}
/**
* Return the first element in an array passing a given truth test.
*
* @param array $array
* @param \Closure $callback
* @param mixed $default
* @return mixed
*/
public static function first($array, $callback, $default = null)
{
foreach ($array as $key => $value)
{
if (call_user_func($callback, $key, $value)) return $value;
}
return static::value($default);
}
/**
* Return the last element in an array passing a given truth test.
*
* @param array $array
* @param \Closure $callback
* @param mixed $default
* @return mixed
*/
public static function last($array, $callback, $default = null)
{
return static::first(array_reverse($array), $callback, $default);
}
/**
* Flatten a multi-dimensional array into a single level.
*
* @param array $array
* @return array
*/
public static function flatten($array)
{
$return = array();
array_walk_recursive($array, function($x) use (&$return) { $return[] = $x; });
return $return;
}
/**
* Remove one or many array items from a given array using "dot" notation.
*
* @param array $array
* @param array|string $keys
* @return void
*/
public static function forget(&$array, $keys)
{
$original =& $array;
foreach ((array) $keys as $key)
{
$parts = explode('.', $key);
while (count($parts) > 1)
{
$part = array_shift($parts);
if (isset($array[$part]) && is_array($array[$part]))
{
$array =& $array[$part];
}
}
unset($array[array_shift($parts)]);
// clean up after each pass
$array =& $original;
}
}
/**
* Get an item from an array using "dot" notation.
*
* @param array $array
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function get($array, $key, $default = null)
{
return static::getItem($array, $key, $default);
}
/**
* Retrieves nested items from array(able) data
* it's the laravel's date_get global function.
*
* @param mixed $target
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function getItem($target, $key, $default = null)
{
if (is_null($key)) return $target;
foreach (explode('.', $key) as $segment) {
if (is_array($target)) {
if (!array_key_exists($segment, $target)) {
return static::value($default);
}
$target = $target[$segment];
} elseif ($target instanceof ArrayAccess) {
if (!isset($target[$segment])) {
return static::value($default);
}
$target = $target[$segment];
} elseif (is_object($target)) {
if (!isset($target->{$segment})) {
return static::value($default);
}
$target = $target->{$segment};
} else {
return static::value($default);
}
}
return $target;
}
/**
* Check if an item exists in an array using "dot" notation.
*
* @param array $array
* @param string $key
* @return bool
*/
public static function has($array, $key)
{
if (empty($array) || is_null($key)) return false;
if (array_key_exists($key, $array)) return true;
foreach (explode('.', $key) as $segment)
{
if ( ! is_array($array) || ! array_key_exists($segment, $array))
{
return false;
}
$array = $array[$segment];
}
return true;
}
/**
* Get a subset of the items from the given array.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function only($array, $keys)
{
return array_intersect_key($array, array_flip((array) $keys));
}
/**
* Pluck an array of values from an array.
*
* @param array $array
* @param string $value
* @param string $key
* @return array
*/
public static function pluck($array, $value, $key = null)
{
$results = array();
foreach ($array as $item)
{
$itemValue = is_object($item) ? $item->{$value} : $item[$value];
// If the key is "null", we will just append the value to the array and keep
// looping. Otherwise we will key the array using the value of the key we
// received from the developer. Then we'll return the final array form.
if (is_null($key))
{
$results[] = $itemValue;
}
else
{
$itemKey = is_object($item) ? $item->{$key} : $item[$key];
$results[$itemKey] = $itemValue;
}
}
return $results;
}
/**
* Get a value from the array, and remove it.
*
* @param array $array
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function pull(&$array, $key, $default = null)
{
$value = static::get($array, $key, $default);
static::forget($array, $key);
return $value;
}
/**
* Set an array item to a given value using "dot" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* @param array $array
* @param string $key
* @param mixed $value
* @return array
*/
public static function set(&$array, $key, $value)
{
if (is_null($key)) return $array = $value;
$keys = explode('.', $key);
while (count($keys) > 1)
{
$key = array_shift($keys);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if ( ! isset($array[$key]) || ! is_array($array[$key]))
{
$array[$key] = array();
}
$array =& $array[$key];
}
$array[array_shift($keys)] = $value;
return $array;
}
/**
* Sort the array using the given Closure.
*
* @param array $array
* @param \Closure $callback
* @return array
*/
public static function sort($array, Closure $callback)
{
return Collection::make($array)->sortBy($callback)->all();
}
/**
* Filter the array using the given Closure.
*
* @param array $array
* @param \Closure $callback
* @return array
*/
public static function where($array, Closure $callback)
{
$filtered = array();
foreach ($array as $key => $value)
{
if (call_user_func($callback, $key, $value)) $filtered[$key] = $value;
}
return $filtered;
}
public static function value($value)
{
return $value instanceof Closure ? $value() : $value;
}
}

View File

@@ -0,0 +1,851 @@
<?php
namespace FluentMail\Includes\Support;
use Closure;
use Countable;
use ArrayAccess;
use ArrayIterator;
use CachingIterator;
use JsonSerializable;
use IteratorAggregate;
use FluentMail\Includes\Support\Arr;
use FluentMail\Includes\Support\Contracts\JsonableInterface;
use FluentMail\Includes\Support\Contracts\ArrayableInterface;
class Collection implements ArrayAccess, ArrayableInterface, Countable, IteratorAggregate, JsonableInterface, JsonSerializable {
/**
* The items contained in the collection.
*
* @var array
*/
protected $items = array();
/**
* Create a new collection.
*
* @param array $items
* @return void
*/
public function __construct(array $items = array())
{
$this->items = $items;
}
/**
* Create a new collection instance if the value isn't one already.
*
* @param mixed $items
* @return static
*/
public static function make($items)
{
if (is_null($items)) return new static;
if ($items instanceof Collection) return $items;
return new static(is_array($items) ? $items : array($items));
}
/**
* Get all of the items in the collection.
*
* @return array
*/
public function all()
{
return $this->items;
}
/**
* Collapse the collection items into a single array.
*
* @return static
*/
public function collapse()
{
$results = array();
foreach ($this->items as $values)
{
if ($values instanceof Collection) $values = $values->all();
$results = array_merge($results, $values);
}
return new static($results);
}
/**
* Determine if an item exists in the collection.
*
* @param mixed $value
* @return bool
*/
public function contains($value)
{
if ($value instanceof Closure)
{
return ! is_null($this->first($value));
}
return in_array($value, $this->items);
}
/**
* Diff the collection with the given items.
*
* @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
* @return static
*/
public function diff($items)
{
return new static(array_diff($this->items, $this->getArrayableItems($items)));
}
/**
* Execute a callback over each item.
*
* @param \Closure $callback
* @return $this
*/
public function each(Closure $callback)
{
array_map($callback, $this->items);
return $this;
}
/**
* Fetch a nested element of the collection.
*
* @param string $key
* @return static
*/
public function fetch($key)
{
return new static(Arr::fetch($this->items, $key));
}
/**
* Run a filter over each of the items.
*
* @param \Closure $callback
* @return static
*/
public function filter(Closure $callback)
{
return new static(array_filter($this->items, $callback));
}
/**
* Get the first item from the collection.
*
* @param \Closure $callback
* @param mixed $default
* @return mixed|null
*/
public function first(?Closure $callback = null, $default = null)
{
if (is_null($callback))
{
return count($this->items) > 0 ? reset($this->items) : null;
}
return Arr::first($this->items, $callback, $default);
}
/**
* Get a flattened array of the items in the collection.
*
* @return static
*/
public function flatten()
{
return new static(Arr::flatten($this->items));
}
/**
* Flip the items in the collection.
*
* @return static
*/
public function flip()
{
return new static(array_flip($this->items));
}
/**
* Remove an item from the collection by key.
*
* @param mixed $key
* @return void
*/
public function forget($key)
{
unset($this->items[$key]);
}
/**
* Get an item from the collection by key.
*
* @param mixed $key
* @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
{
if ($this->offsetExists($key))
{
return $this->items[$key];
}
return value($default);
}
/**
* Group an associative array by a field or Closure value.
*
* @param callable|string $groupBy
* @return static
*/
public function groupBy($groupBy)
{
$results = array();
foreach ($this->items as $key => $value)
{
$results[$this->getGroupByKey($groupBy, $key, $value)][] = $value;
}
return new static($results);
}
/**
* Get the "group by" key value.
*
* @param callable|string $groupBy
* @param string $key
* @param mixed $value
* @return string
*/
protected function getGroupByKey($groupBy, $key, $value)
{
if ( ! is_string($groupBy) && is_callable($groupBy))
{
return $groupBy($value, $key);
}
return Arr::getItem($value, $groupBy);
}
/**
* Key an associative array by a field.
*
* @param string $keyBy
* @return static
*/
public function keyBy($keyBy)
{
$results = [];
foreach ($this->items as $item)
{
$key = Arr::getItem($item, $keyBy);
$results[$key] = $item;
}
return new static($results);
}
/**
* Determine if an item exists in the collection by key.
*
* @param mixed $key
* @return bool
*/
public function has($key)
{
return $this->offsetExists($key);
}
/**
* Concatenate values of a given key as a string.
*
* @param string $value
* @param string $glue
* @return string
*/
public function implode($value, $glue = null)
{
return implode($glue, $this->lists($value));
}
/**
* Intersect the collection with the given items.
*
* @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
* @return static
*/
public function intersect($items)
{
return new static(array_intersect($this->items, $this->getArrayableItems($items)));
}
/**
* Determine if the collection is empty or not.
*
* @return bool
*/
public function isEmpty()
{
return empty($this->items);
}
/**
* Get the keys of the collection items.
*
* @return array
*/
public function keys()
{
return array_keys($this->items);
}
/**
* Get the last item from the collection.
*
* @return mixed|null
*/
public function last()
{
return count($this->items) > 0 ? end($this->items) : null;
}
/**
* Get an array with the values of a given key.
*
* @param string $value
* @param string $key
* @return array
*/
public function lists($value, $key = null)
{
return Arr::pluck($this->items, $value, $key);
}
/**
* Run a map over each of the items.
*
* @param \Closure $callback
* @return static
*/
public function map(Closure $callback)
{
return new static(array_map($callback, $this->items, array_keys($this->items)));
}
/**
* Merge the collection with the given items.
*
* @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->getArrayableItems($items)));
}
/**
* Get and remove the last item from the collection.
*
* @return mixed|null
*/
public function pop()
{
return array_pop($this->items);
}
/**
* Push an item onto the beginning of the collection.
*
* @param mixed $value
* @return void
*/
public function prepend($value)
{
array_unshift($this->items, $value);
}
/**
* Push an item onto the end of the collection.
*
* @param mixed $value
* @return void
*/
public function push($value)
{
$this->items[] = $value;
}
/**
* Pulls an item from the collection.
*
* @param mixed $key
* @param mixed $default
* @return mixed
*/
public function pull($key, $default = null)
{
return Arr::pull($this->items, $key, $default);
}
/**
* Put an item in the collection by key.
*
* @param mixed $key
* @param mixed $value
* @return void
*/
public function put($key, $value)
{
$this->items[$key] = $value;
}
/**
* Get one or more items randomly from the collection.
*
* @param int $amount
* @return mixed
*/
public function random($amount = 1)
{
if ($this->isEmpty()) return null;
$keys = array_rand($this->items, $amount);
return is_array($keys) ? array_intersect_key($this->items, array_flip($keys)) : $this->items[$keys];
}
/**
* Reduce the collection to a single value.
*
* @param callable $callback
* @param mixed $initial
* @return mixed
*/
public function reduce(callable $callback, $initial = null)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* Create a collection of all elements that do not pass a given truth test.
*
* @param \Closure|mixed $callback
* @return static
*/
public function reject($callback)
{
if ($callback instanceof Closure)
{
return $this->filter(function($item) use ($callback)
{
return ! $callback($item);
});
}
return $this->filter(function($item) use ($callback)
{
return $item != $callback;
});
}
/**
* Reverse items order.
*
* @return static
*/
public function reverse()
{
return new static(array_reverse($this->items));
}
/**
* Search the collection for a given value and return the corresponding key if successful.
*
* @param mixed $value
* @param bool $strict
* @return mixed
*/
public function search($value, $strict = false)
{
return array_search($value, $this->items, $strict);
}
/**
* Get and remove the first item from the collection.
*
* @return mixed|null
*/
public function shift()
{
return array_shift($this->items);
}
/**
* Shuffle the items in the collection.
*
* @return $this
*/
public function shuffle()
{
shuffle($this->items);
return $this;
}
/**
* Slice the underlying collection array.
*
* @param int $offset
* @param int $length
* @param bool $preserveKeys
* @return static
*/
public function slice($offset, $length = null, $preserveKeys = false)
{
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
}
/**
* Chunk the underlying collection array.
*
* @param int $size
* @param bool $preserveKeys
* @return static
*/
public function chunk($size, $preserveKeys = false)
{
$chunks = new static;
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk)
{
$chunks->push(new static($chunk));
}
return $chunks;
}
/**
* Sort through each item with a callback.
*
* @param \Closure $callback
* @return $this
*/
public function sort(Closure $callback)
{
uasort($this->items, $callback);
return $this;
}
/**
* Sort the collection using the given Closure.
*
* @param \Closure|string $callback
* @param int $options
* @param bool $descending
* @return $this
*/
public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
{
$results = array();
if (is_string($callback)) $callback =
$this->valueRetriever($callback);
// First we will loop through the items and get the comparator from a callback
// function which we were given. Then, we will sort the returned values and
// and grab the corresponding values for the sorted keys from this array.
foreach ($this->items as $key => $value)
{
$results[$key] = $callback($value);
}
$descending ? arsort($results, $options)
: asort($results, $options);
// Once we have sorted all of the keys in the array, we will loop through them
// and grab the corresponding model so we can set the underlying items list
// to the sorted version. Then we'll just return the collection instance.
foreach (array_keys($results) as $key)
{
$results[$key] = $this->items[$key];
}
$this->items = $results;
return $this;
}
/**
* Sort the collection in descending order using the given Closure.
*
* @param \Closure|string $callback
* @param int $options
* @return $this
*/
public function sortByDesc($callback, $options = SORT_REGULAR)
{
return $this->sortBy($callback, $options, true);
}
/**
* Splice portion of the underlying collection array.
*
* @param int $offset
* @param int $length
* @param mixed $replacement
* @return static
*/
public function splice($offset, $length = 0, $replacement = array())
{
return new static(array_splice($this->items, $offset, $length, $replacement));
}
/**
* Get the sum of the given values.
*
* @param \Closure $callback
* @return mixed
*/
public function sum($callback = null)
{
if (is_null($callback))
{
return array_sum($this->items);
}
if (is_string($callback))
{
$callback = $this->valueRetriever($callback);
}
return $this->reduce(function($result, $item) use ($callback)
{
return $result += $callback($item);
}, 0);
}
/**
* Take the first or last {$limit} items.
*
* @param int $limit
* @return static
*/
public function take($limit = null)
{
if ($limit < 0) return $this->slice($limit, abs($limit));
return $this->slice(0, $limit);
}
/**
* Transform each item in the collection using a callback.
*
* @param \Closure $callback
* @return $this
*/
public function transform(Closure $callback)
{
$this->items = array_map($callback, $this->items);
return $this;
}
/**
* Return only unique items from the collection array.
*
* @return static
*/
public function unique()
{
return new static(array_unique($this->items));
}
/**
* Reset the keys on the underlying array.
*
* @return static
*/
public function values()
{
$this->items = array_values($this->items);
return $this;
}
/**
* Get a value retrieving callback.
*
* @param string $value
* @return \Closure
*/
protected function valueRetriever($value)
{
return function($item) use ($value)
{
return Arr::getItem($item, $value);
};
}
/**
* Get the collection of items as a plain array.
*
* @return array
*/
public function toArray()
{
return array_map(function($value) {
return $value instanceof ArrayableInterface ? $value->toArray() : $value;
}, $this->items);
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
public function jsonSerialize()
{
return $this->toArray();
}
/**
* Get the collection of items as JSON.
*
* @param int $options
* @return string
*/
public function toJson($options = 0)
{
return json_encode($this->toArray(), $options);
}
/**
* Get an iterator for the items.
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->items);
}
/**
* Get a CachingIterator instance.
*
* @param int $flags
* @return \CachingIterator
*/
public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
{
return new CachingIterator($this->getIterator(), $flags);
}
/**
* Count the number of items in the collection.
*
* @return int
*/
public function count()
{
return count($this->items);
}
/**
* Determine if an item exists at an offset.
*
* @param mixed $key
* @return bool
*/
public function offsetExists($key)
{
return array_key_exists($key, $this->items);
}
/**
* Get an item at a given offset.
*
* @param mixed $key
* @return mixed
*/
public function offsetGet($key)
{
return $this->items[$key];
}
/**
* Set the item at a given offset.
*
* @param mixed $key
* @param mixed $value
* @return void
*/
public function offsetSet($key, $value)
{
if (is_null($key))
{
$this->items[] = $value;
}
else
{
$this->items[$key] = $value;
}
}
/**
* Unset the item at a given offset.
*
* @param string $key
* @return void
*/
public function offsetUnset($key)
{
unset($this->items[$key]);
}
/**
* Convert the collection to its string representation.
*
* @return string
*/
public function __toString()
{
return $this->toJson();
}
/**
* Results array of items from Collection or ArrayableInterface.
*
* @param \Illuminate\Support\Collection|\Illuminate\Support\Contracts\ArrayableInterface|array $items
* @return array
*/
protected function getArrayableItems($items)
{
if ($items instanceof Collection)
{
$items = $items->all();
}
elseif ($items instanceof ArrayableInterface)
{
$items = $items->toArray();
}
return $items;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace FluentMail\Includes\Support\Contracts;
interface ArrayableInterface {
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray();
}

View File

@@ -0,0 +1,22 @@
<?php
namespace FluentMail\Includes\Support\Contracts;
interface ContextualBindingBuilderContract
{
/**
* Define the abstract target that depends on the context.
*
* @param string $abstract
* @return $this
*/
public function needs($abstract);
/**
* Define the implementation for the contextual binding.
*
* @param Closure|string $implementation
* @return void
*/
public function give($implementation);
}

View File

@@ -0,0 +1,34 @@
<?php
namespace FluentMail\Includes\Support\Contracts;
interface FileInterface
{
/**
* Returns whether the file was uploaded successfully.
*
* @return bool
*/
public function isValid();
/**
* Gets the path without filename
*
* @return string
*/
public function getPath();
/**
* Take an educated guess of the file's extension.
*
* @return mixed|null
*/
public function guessExtension();
/**
* Returns the original file extension.
*
* @return string
*/
public function getClientOriginalExtension();
}

View File

@@ -0,0 +1,15 @@
<?php
namespace FluentMail\Includes\Support\Contracts;
interface JsonableInterface {
/**
* Convert the object to its JSON representation.
*
* @param int $options
* @return string
*/
public function toJson($options = 0);
}

View File

@@ -0,0 +1,10 @@
<?php
namespace FluentMail\Includes\Support;
use Exception;
class ForbiddenException extends Exception
{
// ...
}

View File

@@ -0,0 +1,70 @@
<?php
namespace FluentMail\Includes\Support;
trait MacroableTrait {
/**
* The registered string macros.
*
* @var array
*/
protected static $macros = array();
/**
* Register a custom macro.
*
* @param string $name
* @param callable $macro
* @return void
*/
public static function macro($name, callable $macro)
{
static::$macros[$name] = $macro;
}
/**
* Checks if macro is registered
*
* @param string $name
* @return boolean
*/
public static function hasMacro($name)
{
return isset(static::$macros[$name]);
}
/**
* Dynamically handle calls to the class.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public static function __callStatic($method, $parameters)
{
if (static::hasMacro($method))
{
return call_user_func_array(static::$macros[$method], $parameters);
}
throw new \BadMethodCallException("Method {$method} does not exist."); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
/**
* Dynamically handle calls to the class.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
return static::__callStatic($method, $parameters);
}
}

View File

@@ -0,0 +1,590 @@
<?php
namespace FluentMail\Includes\Support;
use FluentMail\Includes\Support\MacroableTrait;
class Str {
use MacroableTrait;
/**
* The cache of snake-cased words.
*
* @var array
*/
protected static $snakeCache = [];
/**
* The cache of camel-cased words.
*
* @var array
*/
protected static $camelCache = [];
/**
* The cache of studly-cased words.
*
* @var array
*/
protected static $studlyCache = [];
/**
* Transliterate a UTF-8 value to ASCII.
*
* @param string $value
* @return string
*/
public static function ascii($value)
{
foreach (static::charsArray() as $key => $val) {
$value = str_replace($val, $key, $value);
}
return preg_replace('/[^\x20-\x7E]/u', '', $value);
}
/**
* Convert a value to camel case.
*
* @param string $value
* @return string
*/
public static function camel($value)
{
if (isset(static::$camelCache[$value])) {
return static::$camelCache[$value];
}
return static::$camelCache[$value] = lcfirst(static::studly($value));
}
/**
* Determine if a given string contains a given substring.
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function contains($haystack, $needles)
{
foreach ((array) $needles as $needle) {
if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
return true;
}
}
return false;
}
/**
* Determine if a given string ends with a given substring.
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function endsWith($haystack, $needles)
{
foreach ((array) $needles as $needle) {
if (substr($haystack, -strlen($needle)) === (string) $needle) {
return true;
}
}
return false;
}
/**
* Cap a string with a single instance of a given value.
*
* @param string $value
* @param string $cap
* @return string
*/
public static function finish($value, $cap)
{
$quoted = preg_quote($cap, '/');
return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
}
/**
* Determine if a given string matches a given pattern.
*
* @param string $pattern
* @param string $value
* @return bool
*/
public static function is($pattern, $value)
{
if ($pattern == $value) {
return true;
}
$pattern = preg_quote($pattern, '#');
// Asterisks are translated into zero-or-more regular expression wildcards
// to make it convenient to check if the strings starts with the given
// pattern such as "library/*", making any string check convenient.
$pattern = str_replace('\*', '.*', $pattern);
return (bool) preg_match('#^'.$pattern.'\z#u', $value);
}
/**
* Return the length of the given string.
*
* @param string $value
* @return int
*/
public static function length($value)
{
return mb_strlen($value);
}
/**
* Limit the number of characters in a string.
*
* @param string $value
* @param int $limit
* @param string $end
* @return string
*/
public static function limit($value, $limit = 100, $end = '...')
{
if (mb_strwidth($value, 'UTF-8') <= $limit) {
return $value;
}
return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end;
}
/**
* Convert the given string to lower-case.
*
* @param string $value
* @return string
*/
public static function lower($value)
{
return mb_strtolower($value, 'UTF-8');
}
/**
* Limit the number of words in a string.
*
* @param string $value
* @param int $words
* @param string $end
* @return string
*/
public static function words($value, $words = 100, $end = '...')
{
preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);
if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) {
return $value;
}
return rtrim($matches[0]).$end;
}
/**
* Parse a Class@method style callback into class and method.
*
* @param string $callback
* @param string $default
* @return array
*/
public static function parseCallback($callback, $default)
{
return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
}
/**
* Get the plural form of an English word.
*
* @param string $value
* @param int $count
* @return string
*/
public static function plural($value, $count = 2)
{
return Pluralizer::plural($value, $count);
}
/**
* Generate a more truly "random" alpha-numeric string.
*
* @param int $length
* @return string
*/
public static function random($length = 16)
{
$string = '';
while (($len = strlen($string)) < $length) {
$size = $length - $len;
$bytes = random_bytes($size);
$string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
}
return $string;
}
/**
* Generate a "random" alpha-numeric string.
*
* Should not be considered sufficient for cryptography, etc.
*
* @deprecated since version 5.3. Use the "random" method directly.
*
* @param int $length
* @return string
*/
public static function quickRandom($length = 16)
{
if (PHP_MAJOR_VERSION > 5) {
return static::random($length);
}
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}
/**
* Replace a given value in the string sequentially with an array.
*
* @param string $search
* @param array $replace
* @param string $subject
* @return string
*/
public static function replaceArray($search, array $replace, $subject)
{
foreach ($replace as $value) {
$subject = static::replaceFirst($search, $value, $subject);
}
return $subject;
}
/**
* Replace the first occurrence of a given value in the string.
*
* @param string $search
* @param string $replace
* @param string $subject
* @return string
*/
public static function replaceFirst($search, $replace, $subject)
{
$position = strpos($subject, $search);
if ($position !== false) {
return substr_replace($subject, $replace, $position, strlen($search));
}
return $subject;
}
/**
* Replace the last occurrence of a given value in the string.
*
* @param string $search
* @param string $replace
* @param string $subject
* @return string
*/
public static function replaceLast($search, $replace, $subject)
{
$position = strrpos($subject, $search);
if ($position !== false) {
return substr_replace($subject, $replace, $position, strlen($search));
}
return $subject;
}
/**
* Convert the given string to upper-case.
*
* @param string $value
* @return string
*/
public static function upper($value)
{
return mb_strtoupper($value, 'UTF-8');
}
/**
* Convert the given string to title case.
*
* @param string $value
* @return string
*/
public static function title($value)
{
return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
}
/**
* Get the singular form of an English word.
*
* @param string $value
* @return string
*/
public static function singular($value)
{
return Pluralizer::singular($value);
}
/**
* Generate a URL friendly "slug" from a given string.
*
* @param string $title
* @param string $separator
* @return string
*/
public static function slug($title, $separator = '-')
{
$title = static::ascii($title);
// Convert all dashes/underscores into separator
$flip = $separator == '-' ? '_' : '-';
$title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);
// Remove all characters that are not the separator, letters, numbers, or whitespace.
$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title));
// Replace all separator characters and whitespace by a single separator
$title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);
return trim($title, $separator);
}
/**
* Convert a string to snake case.
*
* @param string $value
* @param string $delimiter
* @return string
*/
public static function snake($value, $delimiter = '_')
{
$key = $value;
if (isset(static::$snakeCache[$key][$delimiter])) {
return static::$snakeCache[$key][$delimiter];
}
if (! ctype_lower($value)) {
$value = preg_replace('/\s+/u', '', $value);
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
}
return static::$snakeCache[$key][$delimiter] = $value;
}
/**
* Determine if a given string starts with a given substring.
*
* @param string $haystack
* @param string|array $needles
* @return bool
*/
public static function startsWith($haystack, $needles)
{
foreach ((array) $needles as $needle) {
if ($needle != '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
return true;
}
}
return false;
}
/**
* Convert a value to studly caps case.
*
* @param string $value
* @return string
*/
public static function studly($value)
{
$key = $value;
if (isset(static::$studlyCache[$key])) {
return static::$studlyCache[$key];
}
$value = ucwords(str_replace(['-', '_'], ' ', $value));
return static::$studlyCache[$key] = str_replace(' ', '', $value);
}
/**
* Returns the portion of string specified by the start and length parameters.
*
* @param string $string
* @param int $start
* @param int|null $length
* @return string
*/
public static function substr($string, $start, $length = null)
{
return mb_substr($string, $start, $length, 'UTF-8');
}
/**
* Make a string's first character uppercase.
*
* @param string $string
* @return string
*/
public static function ucfirst($string)
{
return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
}
/**
* Returns the replacements for the ascii method.
*
* Note: Adapted from Stringy\Stringy.
*
* @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
*
* @return array
*/
protected static function charsArray()
{
static $charsArray;
if (isset($charsArray)) {
return $charsArray;
}
return $charsArray = [
'0' => ['°', '₀', '۰'],
'1' => ['¹', '₁', '۱'],
'2' => ['²', '₂', '۲'],
'3' => ['³', '₃', '۳'],
'4' => ['⁴', '₄', '۴', '٤'],
'5' => ['⁵', '₅', '۵', '٥'],
'6' => ['⁶', '₆', '۶', '٦'],
'7' => ['⁷', '₇', '۷'],
'8' => ['⁸', '₈', '۸'],
'9' => ['⁹', '₉', '۹'],
'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا'],
'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ'],
'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ'],
'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
'm' => ['м', 'μ', 'م', 'မ', 'მ'],
'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ'],
'p' => ['п', 'π', 'ပ', 'პ', 'پ'],
'q' => [''],
'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ'],
'v' => ['в', 'ვ', 'ϐ'],
'w' => ['ŵ', 'ω', 'ώ', '', 'ွ'],
'x' => ['χ', 'ξ'],
'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
'aa' => ['ع', 'आ', 'آ'],
'ae' => ['ä', 'æ', 'ǽ'],
'ai' => ['ऐ'],
'at' => ['@'],
'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
'dj' => ['ђ', 'đ'],
'dz' => ['џ', 'ძ'],
'ei' => ['ऍ'],
'gh' => ['غ', 'ღ'],
'ii' => ['ई'],
'ij' => ['ij'],
'kh' => ['х', 'خ', 'ხ'],
'lj' => ['љ'],
'nj' => ['њ'],
'oe' => ['ö', 'œ', 'ؤ'],
'oi' => ['ऑ'],
'oii' => ['ऒ'],
'ps' => ['ψ'],
'sh' => ['ш', 'შ', 'ش'],
'shch' => ['щ'],
'ss' => ['ß'],
'sx' => ['ŝ'],
'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
'ts' => ['ц', 'ც', 'წ'],
'ue' => ['ü'],
'uu' => ['ऊ'],
'ya' => ['я'],
'yu' => ['ю'],
'zh' => ['ж', 'ჟ', 'ژ'],
'(c)' => ['©'],
'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ'],
'B' => ['Б', 'Β', 'ब'],
'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
'F' => ['Ф', 'Φ'],
'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
'H' => ['Η', 'Ή', 'Ħ'],
'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
'K' => ['К', 'Κ'],
'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
'M' => ['М', 'Μ'],
'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
'P' => ['П', 'Π'],
'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ'],
'V' => ['В'],
'W' => ['Ω', 'Ώ', 'Ŵ'],
'X' => ['Χ', 'Ξ'],
'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
'AE' => ['Ä', 'Æ', 'Ǽ'],
'CH' => ['Ч'],
'DJ' => ['Ђ'],
'DZ' => ['Џ'],
'GX' => ['Ĝ'],
'HX' => ['Ĥ'],
'IJ' => ['IJ'],
'JX' => ['Ĵ'],
'KH' => ['Х'],
'LJ' => ['Љ'],
'NJ' => ['Њ'],
'OE' => ['Ö', 'Œ'],
'PS' => ['Ψ'],
'SH' => ['Ш'],
'SHCH' => ['Щ'],
'SS' => ['ẞ'],
'TH' => ['Þ'],
'TS' => ['Ц'],
'UE' => ['Ü'],
'YA' => ['Я'],
'YU' => ['Ю'],
'ZH' => ['Ж'],
' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"],
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FluentMail\Includes\Support;
use Exception;
class ValidationException extends Exception
{
public function __construct($message = "", $code = 0 , Exception $previous = NULL, $errors = [])
{
$this->errors = $errors;
parent::__construct($message, $code, $previous);
}
public function errors()
{
return $this->errors;
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace FluentMail\Includes\View;
use Exception;
class View
{
protected $app;
protected $path;
protected $data = [];
protected static $sharedData = [];
public function __construct($app)
{
$this->app = $app;
}
/**
* Generate and echo/print a view file
* @param string $path
* @param array $data
* @return void
*/
public function render($path, $data = [])
{
echo $this->make($path, $data); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Generate a view file
* @param string $path
* @param array $data
* @return string [generated html]
* @throws Exception
*/
public function make($path, $data = [])
{
if (file_exists($this->path = $this->resolveFilePath($path))) {
$this->data = $data;
return $this;
}
throw new Exception("The view file [{$this->path}] doesn't exists!"); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
/**
* Resolve the view file path
* @param string $path
* @return string
*/
protected function resolveFilePath($path)
{
$path = str_replace('.', DIRECTORY_SEPARATOR, $path);
return $this->app['path.views'] . $path .'.php';
}
/**
* Evaluate the view file
* @param string $path
* @param string $data
* @return $this
*/
protected function renderContent()
{
$renderOutput = function($app) {
ob_start() && extract(
$this->gatherData(), EXTR_SKIP
);
include $this->path;
return ltrim(ob_get_clean());
};
return $renderOutput($this->app);
}
/**
* Gether shared & view data
* @return array
*/
protected function gatherData()
{
return array_merge(static::$sharedData, $this->data);
}
/**
* Share global data for any view
* @param string $key
* @param mixed $value
* @return void
*/
public function share($key, $value)
{
static::$sharedData[$key] = $value;
}
/**
* Provides a fluent interface to set data
* @param mixed $key
* @param mixed $data
* @return $this
*/
public function with($name, $data = [])
{
if (is_array($name)) {
foreach ($name as $key => $value) {
$this->__set($key, $value);
}
} else {
$this->__set($name, $data);
}
return $this;
}
/**
* Setter for the view
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
$this->data[$key] = $value;
}
/**
* Dump the view result
* @return string
*/
public function __toString()
{
return $this->renderContent();
}
}

View File

@@ -0,0 +1 @@
<?php // silence is golden

View File

@@ -0,0 +1 @@
{ "autoload": { "classmap": [""] } }

View File

@@ -0,0 +1,9 @@
<?php // silence is golden
/**
*
* Remove the build folder
* run composer install --no-dev
* That's it
*/

View File

@@ -0,0 +1,46 @@
{
"name": "fluent-smtp/fluent-smtp-3rd-party",
"description": "FluentSMTP 3rd pary Libs",
"license": "Apache-2.0",
"type": "wordpress-plugin",
"homepage": "https://fluentsmtp.com",
"require-dev": {},
"require": {
"google/apiclient": "^2.14.0"
},
"extra": {
"google/apiclient-services": [
"Gmail"
]
},
"config": {
"platform": {
"php": "7.4.33"
},
"sort-packages": true
},
"autoload": {
},
"scripts": {
"post-install-cmd": [
"@prefix-dependencies"
],
"post-update-cmd": [
"@prefix-dependencies"
],
"prefix-dependencies": [
"mkdir -p php-scoper && echo '{ \"require\": { \"humbug/php-scoper\": \"^0.13.0\" }, \"config\": { \"platform\": { \"php\": \"7.4\" }, \"allow-plugins\": { \"composer/package-versions-deprecated\": true } }, \"minimum-stability\": \"dev\", \"prefer-stable\": true }' > php-scoper/composer.json",
"@composer --working-dir=php-scoper install",
"@php -dxdebug.mode=off php-scoper/vendor/bin/php-scoper add --output-dir=./build/vendor --force --quiet",
"rm -rf php-scoper",
"@autoload-third-party"
],
"autoload-third-party": [
"echo '{ \"autoload\": { \"classmap\": [\"\"] } }' > build/composer.json",
"@composer --working-dir=build dump-autoload --classmap-authoritative --no-interaction",
"cp vendor/composer/autoload_files.php build/vendor/composer",
"rm -rf vendor && rm -rf composer.lock",
"rm -rf build/vendor/scoper-autoload.php"
]
}
}

View File

@@ -0,0 +1,9 @@
<?php // silence is golden
/**
*
* Remove the build folder
* run composer install --no-dev
* That's it
*/

View File

@@ -0,0 +1,132 @@
<?php
/**
* PHP-Scoper configuration file.
*
* @package Google\Site_Kit
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
use Symfony\Component\Finder\Finder;
// Google API services to include classes for.
$google_services = implode(
'|',
array(
'Gmail'
)
);
return array(
'prefix' => 'FluentSmtpLib',
'finders' => array(
// General dependencies, except Google API services.
Finder::create()
->files()
->ignoreVCS( true )
->notName( '/LICENSE|.*\\.md|.*\\.dist|Makefile|composer\\.(json|lock)/' )
->exclude(
array(
'doc',
'test',
'test_old',
'tests',
'Tests',
'vendor-bin',
)
)
->path( '#^firebase/php-jwt#' )
->path( '#^google/apiclient/#' )
->path( '#^google/auth/#' )
->path( '#^guzzlehttp/#' )
->path( '#^monolog/#' )
->path( '#^phpseclib/phpseclib/phpseclib/#' )
->path( '#^psr/#' )
->path( '#^ralouphie/#' )
->path( '#^react/#' )
->path( '#^symfony/#' )
->path( '#^true/#' )
->in( 'vendor' ),
// Google API service infrastructure classes.
Finder::create()
->files()
->ignoreVCS( true )
->notName( '/LICENSE|.*\\.md|.*\\.dist|Makefile|composer\\.json|composer\\.lock/' )
->exclude(
array(
'doc',
'test',
'test_old',
'tests',
'Tests',
'vendor-bin',
)
)
->path( "#^google/apiclient-services/src/($google_services)/#" )
->in( 'vendor' ),
// Google API service entry classes.
Finder::create()
->files()
->ignoreVCS( true )
->name( "#^($google_services)\.php$#" )
->depth( '== 0' )
->in( 'vendor/google/apiclient-services/src' ),
Finder::create()
->files()
->ignoreVCS( true )
->name( '#^autoload.php$#' )
->depth( '== 0' )
->in( 'vendor/google/apiclient-services' ),
),
'files-whitelist' => array(
// This dependency is a global function which should remain global.
'vendor/ralouphie/getallheaders/src/getallheaders.php',
),
'patchers' => array(
function ( $file_path, $prefix, $contents ) {
// Avoid prefixing the `static` keyword in some places.
$contents = str_replace( "\\$prefix\\static", 'static', $contents );
if ( preg_match( '#google/apiclient/src/Google/Http/REST\.php$#', $file_path ) ) {
$contents = str_replace( "\\$prefix\\intVal", '\\intval', $contents );
}
if ( false !== strpos( $file_path, 'vendor/google/apiclient/' ) || false !== strpos( $file_path, 'vendor/google/auth/' ) ) {
// Use modified prefix just for this patch.
$s_prefix = str_replace( '\\', '\\\\', $prefix );
$contents = str_replace( "'\\\\GuzzleHttp\\\\ClientInterface", "'\\\\" . $s_prefix . '\\\\GuzzleHttp\\\\ClientInterface', $contents );
$contents = str_replace( '"\\\\GuzzleHttp\\\\ClientInterface', '"\\\\' . $s_prefix . '\\\\GuzzleHttp\\\\ClientInterface', $contents );
$contents = str_replace( "'GuzzleHttp\\\\ClientInterface", "'" . $s_prefix . '\\\\GuzzleHttp\\\\ClientInterface', $contents );
$contents = str_replace( '"GuzzleHttp\\\\ClientInterface', '"' . $s_prefix . '\\\\GuzzleHttp\\\\ClientInterface', $contents );
}
if ( false !== strpos( $file_path, 'vendor/google/apiclient/' ) ) {
$contents = str_replace( "'Google_", "'" . $prefix . '\Google_', $contents );
$contents = str_replace( '"Google_', '"' . $prefix . '\Google_', $contents );
}
if ( false !== strpos( $file_path, 'phpseclib' ) ) {
// Use modified prefix just for this patch.
$s_prefix = str_replace( '\\', '\\\\', $prefix );
$contents = str_replace( "'phpseclib3\\\\", "'\\\\" . $s_prefix . '\\\\phpseclib3\\\\', $contents );
$contents = str_replace( "'\\\\phpseclib3", "'\\\\" . $s_prefix . '\\\\phpseclib3', $contents );
}
if (
// Bootstrap files polyfill global functions using namespaced implementations.
preg_match( '#vendor/symfony/polyfill-.*/bootstrap\.php$#', $file_path )
// The classes under Resources/stubs polyfill classes in the global namespace loaded via classmap.
|| preg_match( '#vendor/symfony/polyfill-.*/Resources/stubs/.*\.php$#', $file_path )
) {
$contents = str_replace( "namespace $prefix;", "/* namespace $prefix intentionally removed */", $contents );
}
return $contents;
},
),
'whitelist' => array(),
'whitelist-global-constants' => false,
'whitelist-global-classes' => false,
'whitelist-global-functions' => false,
);

View File

@@ -0,0 +1 @@
<?php // silence is golden