first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
<?php
namespace WPML\LIB\WP;
use WPML\FP\Logic;
use WPML\FP\Str;
use function WPML\FP\pipe;
class Attachment {
private static $withOutSizeRegEx = '/-\d+[Xx]\d+\./';
/**
* @param string $url
*
* @return int|null The found post ID, or null on failure.
*/
public static function idFromUrl( $url ) {
$removeSize = Str::pregReplace( self::$withOutSizeRegEx, '.' );
return Logic::firstSatisfying(
function ( $id ) { return $id !== 0; },
[
'attachment_url_to_postid',
pipe( $removeSize, 'attachment_url_to_postid' ),
[ self::class, 'idByGuid' ],
pipe( $removeSize, [ self::class, 'idByGuid' ] ),
],
$url
);
}
/**
* @param string $url
*
* @return int The found post ID, or 0 on failure.
*/
public static function idByGuid( $url ) {
global $wpdb;
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid='%s'", $url ) );
return $attachment && count( $attachment )
? $attachment[0]
: 0;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Fns;
use WPML\FP\Maybe;
use function WPML\FP\curryN;
/**
* Class Cache
* @package WPML\LIB\WP
* @method static callable|mixed memorize( ...$group, ...$fn ) :: string → callable → mixed
* @method static callable|mixed memorizeWithCheck( ...$group, ...$checkingFn, ...$fn ) :: string → callable → callable → mixed
* @method static callable|bool set( ...$group, ...$key, ...$value ) :: string → string → mixed → bool
* @method static callable|Maybe get( ...$group, ...$key ) :: string → string → Nothing | Just( mixed )
*/
class Cache {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'get', curryN( 2, [ self::class, 'getInternal' ] ) );
self::macro( 'set', curryN( 3, [ self::class, 'setInternal' ] ) );
self::macro( 'memorizeWithCheck', curryN( 3, function ( $group, $checkingFn, $fn ) {
return function () use ( $fn, $group, $checkingFn ) {
$args = func_get_args();
$key = serialize( $args );
$result = Cache::get( $group, $key );
if ( Fns::isNothing( $result ) || ! $checkingFn( $result->get() ) ) {
$result = call_user_func_array( $fn, $args );
Cache::set( $group, $key, $result );
return $result;
}
return $result->get();
};
} ) );
self::macro( 'memorize', self::memorizeWithCheck( Fns::__, Fns::always( true ), Fns::__ ) );
}
/**
* @param string $group
* @param string $key
*
* @return \WPML\FP\Just|\WPML\FP\Nothing
*/
public static function getInternal( $group, $key ) {
$found = false;
$result = wp_cache_get( $key, $group, false, $found );
if( $found && is_array( $result ) && array_key_exists( 'data', $result ) ) {
return Maybe::just( $result['data'] );
}
return Maybe::nothing();
}
/**
* @param string $group
* @param string $key
* @param mixed $value
*
* @return bool|true
*/
public static function setInternal( $group, $key, $value ) {
// Save $value in an array. We need to do this because W3TC and Redis have bug with saving null.
return wp_cache_set( $key, [ 'data' => $value ], $group );
}
}
Cache::init();

View File

@@ -0,0 +1,30 @@
<?php
namespace WPML\LIB\WP;
use WPML\FP\Curryable;
use WPML\FP\Logic;
use WPML\FP\Str;
/**
* @method static callable|bool hasBlock( ...$string ) - Curried :: string → bool
* @method static callable|bool doesNotHaveBlock( ...$string ) - Curried :: string → bool
* @method static callable|bool stripBlockData( ...$string ) - Curried :: string → string
*/
class Gutenberg {
use Curryable;
const GUTENBERG_OPENING_START = '<!-- wp:';
/**
* @return void
*/
public static function init() {
self::curryN( 'hasBlock', 1, Str::includes( self::GUTENBERG_OPENING_START ) );
self::curryN( 'doesNotHaveBlock', 1, Logic::complement( self::hasBlock() ) );
self::curryN( 'stripBlockData', 1, Str::pregReplace( '(<!--\s*/?wp:[^<]*-->)', '' ) );
}
}
Gutenberg::init();

View File

@@ -0,0 +1,77 @@
<?php
namespace WPML\LIB\WP;
use WPML\FP\Either;
use WPML\FP\Lst;
use WPML\FP\Obj;
use WPML\FP\Promise;
use function WPML\FP\pipe;
class Hooks {
/**
* @param string|string[] $action
* @param int $priority
* @param int $accepted_args
*
* @return \WPML\FP\Promise
*/
public static function onAction( $action, $priority = 10, $accepted_args = 1 ) {
return self::onHook( 'add_action', $action, $priority, $accepted_args );
}
/**
* @param string|string[] $filter
* @param int $priority
* @param int $accepted_args
*
* @return \WPML\FP\Promise
*/
public static function onFilter( $filter, $priority = 10, $accepted_args = 1 ) {
return self::onHook( 'add_filter', $filter, $priority, $accepted_args );
}
/**
* @param callable $fn
* @param string|string[] $actionOrFilter
* @param int $priority
* @param int $accepted_args
*
* @return \WPML\FP\Promise
*/
public static function onHook( callable $fn, $actionOrFilter, $priority = 10, $accepted_args = 1 ) {
$actionsOrFilters = is_array( $actionOrFilter ) ? $actionOrFilter : [ $actionOrFilter ];
$promise = new Promise();
$callback = function () use ( $promise ) {
return $promise->resolve( Either::right( func_get_args() ) )->getOrElse( null );
};
foreach ( $actionsOrFilters as $actionOrFilter ) {
$fn( $actionOrFilter, $callback, $priority, $accepted_args );
};
return $promise;
}
public static function callWithFilter( $fn, $name, $filterFn, $priority = 10, $acceptedArgs = 1 ) {
add_filter( $name, $filterFn, $priority, $acceptedArgs );
$result = $fn();
remove_filter( $name, $filterFn, $priority, $acceptedArgs );
return $result;
}
public static function getArgs( array $argsLabels ) {
return pipe(
Obj::pick( Obj::keys( $argsLabels ) ),
Obj::values(),
Lst::zipObj( Obj::values( $argsLabels ) )
);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Either;
use WPML\FP\Fns;
use function WPML\FP\curryN;
/**
* @method static callable|Either post( ...$url, ...$args ) - Curried :: string → array → Left( WP_Error ) | Right(string)
*/
class Http {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'post', curryN( 2, function ( $url, $args ) {
return WordPress::handleError( Fns::make( \WP_Http::class )->post( $url, $args ) );
} ) );
}
}
Http::init();

View File

@@ -0,0 +1,37 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Collection;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Either;
use function WPML\FP\curryN;
use function WPML\FP\partial;
/**
* @method static callable|Either verify(string ...$action, Collection ...$data) - Curried :: string -> Collection -> Left('Nonce error') | Right(Collection)
* @method static callable|Either verifyEndPoint(Collection ...$data) - Curried :: Collection -> Left('Nonce error') | Right(Collection)
* @method static callable|string create(string ...$action ) - Curried :: string -> string
*/
class Nonce {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'verify', curryN( 2, function ( $action, Collection $postData ) {
return wp_verify_nonce( $postData->get( 'nonce' ), $action ?: $postData->get( 'endpoint' ) )
? Either::right( $postData )
: Either::left( 'Nonce error' );
} ) );
self::macro( 'verifyEndPoint', self::verify( '' ) );
self::macro( 'create', curryN( 1, function( $str ) { return wp_create_nonce( $str ); } ) );
}
}
Nonce::init();

View File

@@ -0,0 +1,33 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use function WPML\FP\curryN;
use function WPML\FP\partialRight;
/**
* @method static callable|mixed get( ...$name ) - Curried :: string → mixed
* @method static callable|mixed getOr( ...$name, ...$default ) - Curried :: string → mixed → mixed
* @method static callable|bool update( ...$name, ...$value ) - Curried :: string → mixed → bool
* @method static callable|bool updateWithoutAutoLoad( ...$name, ...$value ) - Curried :: string → mixed → bool
* @method static callable|bool delete( ...$name ) - Curried :: string → bool
*/
class Option {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'get', curryN( 1, 'get_option' ) );
self::macro( 'getOr', curryN( 2, 'get_option' ) );
self::macro( 'update', curryN( 2, 'update_option' ) );
self::macro( 'updateWithoutAutoLoad', curryN( 2, partialRight( 'update_option', false ) ) );
self::macro( 'delete', curryN( 1, 'delete_option' ) );
}
}
Option::init();

View File

@@ -0,0 +1,76 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Either;
use WPML\FP\Fns;
use WPML\FP\Logic;
use WPML\FP\Lst;
use function WPML\FP\curryN;
use function WPML\FP\gatherArgs;
use function WPML\FP\partialRight;
use function WPML\FP\pipe;
/**
* Class Post
* @package WPML\LIB\WP
* @method static callable|Either getTerms( ...$postId, ...$taxonomy ) - Curried:: int → string → Either false|WP_Error [WP_Term]
* @method static callable|mixed getMetaSingle( ...$postId, ...$key ) - Curried :: int → string → mixed
* @method static callable|int|bool updateMeta( ...$postId, ...$key, ...$value ) - Curried :: int → string → mixed → int|bool
* @method static callable|bool deleteMeta( ...$postId, ...$key ) - Curried :: int → string → bool
* @method static callable|string|false getType( ...$postId ) - Curried :: int → string|bool
* @method static callable|\WP_Post|null get( ...$postId ) - Curried :: int → \WP_Post|null
* @method static callable|string|false getStatus( ...$postId ) - Curried :: int → string|bool
* @method static callable|int update(...$data) - Curried :: array -> int
* @method static callable|int insert(...$data) - Curried :: array -> int
* @method static callable|int setStatus(...$id, ...$status) - Curried :: int -> string -> int
* @method static callable|int setStatusWithoutFilters(...$id, ...$status) - Curried :: int -> string -> int
* @method static callable|\WP_Post|false|null delete(...$id) - Curried :: int -> \WP_Post|false|null
* @method static callable|\WP_Post|false|null trash(...$id) - Curried :: int -> \WP_Post|false|null
*/
class Post {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'getTerms', curryN( 2, pipe(
'get_the_terms',
Logic::ifElse( Logic::isArray(), [ Either::class, 'right' ], [ Either::class, 'left' ] )
) ) );
self::macro( 'getMetaSingle', curryN( 2, partialRight( 'get_post_meta', true ) ) );
self::macro( 'updateMeta', curryN( 3, 'update_post_meta' ) );
self::macro( 'deleteMeta', curryN( 2, 'delete_post_meta' ) );
self::macro( 'getType', curryN( 1, 'get_post_type' ) );
self::macro( 'get', curryN( 1, Fns::unary( 'get_post' ) ) );
self::macro( 'getStatus', curryN( 1, 'get_post_status' ) );
self::macro( 'update', curryN( 1, Fns::unary( 'wp_update_post' ) ) );
self::macro( 'insert', curryN( 1, Fns::unary( 'wp_insert_post' ) ) );
self::macro( 'setStatus', curryN(2, gatherArgs( pipe( Lst::zipObj( [ 'ID', 'post_status' ] ), self::update() ) ) ) );
self::macro( 'setStatusWithoutFilters', curryN( 2, function ( $id, $newStatus ) {
global $wpdb;
return $wpdb->update( $wpdb->posts, [ 'post_status' => $newStatus ], [ 'ID' => $id ] ) ? $id : 0;
} ) );
self::macro( 'delete', curryN( 1, partialRight( 'wp_delete_post', true ) ) );
self::macro( 'trash', curryN( 1, partialRight( 'wp_delete_post', false ) ) );
}
}
Post::init();

View File

@@ -0,0 +1,39 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Fns;
use WPML\FP\Just;
use WPML\FP\Nothing;
use WPML\FP\Maybe;
use function WPML\FP\curryN;
use WPML\FP\Obj;
use function WPML\FP\pipe;
/**
* Class PostType
* @package WPML\LIB\WP
* @method static callable|int getPublishedCount( ...$postType ) - Curried :: string → int
* @method static callable|Just|Nothing getObject( ...$postType ) - Curried :: string → Maybe( WP_Post_Type )|Nothing
* @method static callable|Just|Nothing getPluralName( ...$postType ) - Curried :: string → Maybe(string) |Nothing
* @method static callable|Just|Nothing getSingularName( ...$postType ) - Curried :: string → Maybe(string) |Nothing
*/
class PostType {
use Macroable;
/**
* @return void
*/
public static function init() {
self::macro( 'getPublishedCount', curryN( 1, pipe( 'wp_count_posts', Obj::propOr( 0, 'publish' ) ) ) );
self::macro( 'getObject', curryN( 1, pipe( Maybe::of(), Fns::map( 'get_post_type_object' ) ) ) );
self::macro( 'getPluralName', curryN( 1, pipe( self::getObject(), Fns::map( Obj::path( [ 'labels', 'name' ] ) ) ) ) );
self::macro( 'getSingularName', curryN( 1, pipe( self::getObject(), Fns::map( Obj::path( [ 'labels', 'singular_name' ] ) ) ) ) );
}
}
PostType::init();

View File

@@ -0,0 +1,72 @@
<?php
namespace WPML\LIB\WP\App;
use WPML\FP\Fns;
use WPML\FP\Obj;
use WPML\LIB\WP\Nonce;
use WPML\LIB\WP\WordPress;
class Resources {
/**
* Enqueue a JavaScript application file from the dist directory.
*
* @param string $app
* @param string $pluginBaseUrl
* @param string $pluginBasePath
* @param string $version
* @param null|string $domain
* @param null|string[] $localize
*
* @return void
*/
public static function enqueue( $app, $pluginBaseUrl, $pluginBasePath, $version, $domain = null, $localize = null ) {
$handle = "wpml-$app-ui";
wp_register_script(
$handle,
"$pluginBaseUrl/dist/js/$app/app.js",
[],
$version
);
if ( $localize ) {
if ( isset( $localize['data']['endpoint'] ) ) {
$localize['data']['nonce'] = Nonce::create( $localize['data']['endpoint'] );
}
if ( isset( $localize['data']['endpoints'] ) ) {
$localize = Obj::over(
Obj::lensPath( [ 'data', 'endpoints' ] ),
Fns::map( function ( $endpoint ) {
return [
'endpoint' => $endpoint,
'nonce' => Nonce::create( $endpoint )
];
} ),
$localize
);
}
wp_localize_script( $handle, $localize['name'], $localize['data'] );
}
wp_enqueue_script( $handle );
if ( file_exists( "$pluginBasePath/dist/css/$app/styles.css" ) ) {
wp_enqueue_style(
$handle,
"$pluginBaseUrl/dist/css/$app/styles.css",
[],
$version
);
}
if ( $domain && WordPress::versionCompare( '>=', '5.0.0' ) ) {
$rootPath = $domain === 'wpml-translation-management' && defined( 'WPML_PLUGIN_PATH' )
? WPML_PLUGIN_PATH
: $pluginBasePath;
wp_set_script_translations( $handle, $domain, "$rootPath/locale/jed" );
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace WPML\LIB\WP;
use WPML\FP\Obj;
use function WPML\FP\curryN;
class Roles {
public static function hasCap( $cap = null, $role = null ) {
$hasCap = function ( $cap, $role ) {
global $wp_roles;
return Obj::pathOr( false, [ $role, 'capabilities', $cap ], $wp_roles->roles );
};
return call_user_func_array( curryN( 2, $hasCap ), func_get_args() );
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use function WPML\FP\curryN;
/**
* @method static callable|mixed get( ...$name ) - Curried :: string → mixed
* @method static callable|mixed getOr( ...$name, ...$default ) - Curried :: string → mixed → mixed
* @method static callable|mixed set( ...$name, ...$value, ...$expiration ) - Curried :: string → mixed → int -> mixed
* @method static callable|mixed delete( ...$name ) - Curried :: string → mxied
*/
class Transient {
use Macroable;
public static function init() {
self::macro( 'get', curryN( 1, 'get_transient' ) );
self::macro( 'getOr', curryN( 2, function ( $key, $default ) {
return self::get( $key ) ?: $default;
} ) );
self::macro( 'set', curryN( 3, 'set_transient' ) );
self::macro( 'delete', curryN( 1, 'delete_transient' ) );
}
}
Transient::init();

View File

@@ -0,0 +1,39 @@
<?php
namespace WPML\LIB\WP;
use WPML\Collect\Support\Traits\Macroable;
use WPML\FP\Str;
use function WPML\FP\curryN;
/**
* Class Url
* @package WPML\LIB\WP
*
* @method static callable|mixed isAdmin( ...$url ) - Curried :: string → bool
* @method static callable|mixed isLogin( ...$url ) - Curried :: string → bool
* @method static callable|mixed isContentDirectory( ...$url ) - Curried :: string → bool
*/
class Url {
use Macroable;
/**
* @return bool
*/
public static function init() {
self::macro( 'isLogin', curryN( 1, function ( $url ) {
return Str::includes( wp_login_url(), $url );
} ) );
self::macro( 'isAdmin', curryN( 1, function ( $url ) {
return Str::includes( admin_url(), $url );
} ) );
self::macro( 'isContentDirectory', curryN( 1, function ( $url ) {
return Str::includes( WP_CONTENT_URL, $url );
} ) );
}
}
Url::init();

View File

@@ -0,0 +1,132 @@
<?php
namespace WPML\LIB\WP;
use function WPML\FP\curryN;
use function WPML\FP\partialRight;
use WPML\FP\Fns;
class User {
/**
* @return int
*/
public static function getCurrentId() {
return get_current_user_id();
}
/**
* @return \WP_User|null
*/
public static function getCurrent() {
return wp_get_current_user();
}
/**
* Curried function to update the user meta.
*
* @param int $userId
* @param string $metaKey
* @param mixed $metaValue
*
* @return callable|int|bool
*/
public static function updateMeta( $userId = null, $metaKey = null, $metaValue = null ) {
return call_user_func_array( curryN( 3, 'update_user_meta' ), func_get_args() );
}
/**
* Curried function to get the user meta
*
* @param int $userId
* @param string $metaKey
*
* @return callable|mixed
*/
public static function getMetaSingle( $userId = null, $metaKey = null ) {
return call_user_func_array( curryN( 2, partialRight( 'get_user_meta', true ) ), func_get_args() );
}
/**
* Curried function to get the user meta
*
* @param int $userId
* @param string $metaKey
*
* @return callable|bool
*/
public static function deleteMeta( $userId = null, $metaKey = null ) {
return call_user_func_array( curryN( 2, 'delete_user_meta' ), func_get_args() );
}
/**
* @param int|null $userId
*
* @return callable|\WP_User
*/
public static function get( $userId = null ) {
return call_user_func_array( curryN( 1, function ( $userId ) {
return new \WP_User( $userId );
} ), func_get_args() );
}
/**
* @param array|null $data
*
* @return callable|int|\WP_Error
*/
public static function insert( $data = null ) {
return call_user_func_array( curryN( 1, 'wp_insert_user' ), func_get_args() );
}
/**
* @param int|null $userId
*
* @return callable|int
*/
public static function notifyNew( $userId = null ) {
return call_user_func_array( curryN( 1, Fns::tap( 'wp_send_new_user_notifications' ) ), func_get_args() );
}
/**
* Add the avatar to a user.
*
* @param object|\WP_User $user
*
* @return callable|object
*/
public static function withAvatar( $user = null ) {
$withAvatar = function ( $user ) {
$user->avatar = get_avatar( $user->ID );
$user->avatarUrl = get_avatar_url( $user->ID );
return $user;
};
return call_user_func_array( curryN( 1, $withAvatar ), func_get_args() );
}
/**
* Add the edit link to a user.
*
* @param object|\WP_User $user
*
* @return callable|object
*/
public static function withEditLink( $user = null ) {
$withEditLink = function ( $user ) {
$user->editLink = esc_url(
add_query_arg(
'wp_http_referer',
urlencode( esc_url( stripslashes( $_SERVER['REQUEST_URI'] ) ) ),
"user-edit.php?user_id={$user->ID}"
)
);
return $user;
};
return call_user_func_array( curryN( 1, $withEditLink ), func_get_args() );
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace WPML\LIB\WP;
use WPML\FP\Either;
use WPML\FP\Logic;
class WordPress {
/**
* Compare the WordPress version.
* @param string $operator
* @param string $version
*
* @return bool
*/
public static function versionCompare( $operator, $version ) {
global $wp_version;
return version_compare( $wp_version, $version, $operator );
}
/**
* @param mixed $var
*
* @return \WPML\FP\Either|callable
*/
public static function handleError( $var = null ) {
return call_user_func_array( Logic::ifElse( 'is_wp_error', Either::left(), Either::right() ), func_get_args() );
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace WPML\LIB\WP;
class WPDB {
/**
* It prevents MySQL errors in debug.log.
*
* @param callable $func
*
* @return mixed
*/
public static function withoutError( callable $func ) {
/** @var \wpdb $wpdb */
global $wpdb;
$originalSuppressErrors = $wpdb->suppress_errors;
$wpdb->suppress_errors( true );
$result = $func();
$wpdb->suppress_errors( $originalSuppressErrors );
return $result;
}
}