From 58fca9bae903c3e829068c025168468938b66405 Mon Sep 17 00:00:00 2001 From: Kevin Dees Date: Wed, 16 Oct 2019 13:30:16 -0400 Subject: [PATCH] update to core v4.0.71 --- admin-configure.php | 1 + typerocket-framework.php | 13 +++-- .../typerocket/core/functions/helpers.php | 52 ++++++++++++++++- .../typerocket/core/src/Core/Injector.php | 43 ++++++++++++++ .../core/src/Database/ResultsMeta.php | 10 ++++ .../core/src/Elements/Fields/Field.php | 20 ++++++- .../typerocket/core/src/Elements/Form.php | 42 +++++++++++--- .../Elements/Traits/FormConnectorTrait.php | 5 +- .../core/src/Elements/Traits/OptionsTrait.php | 2 +- .../src/Http/Responders/CommentsResponder.php | 3 +- .../src/Http/Responders/PostsResponder.php | 2 +- .../src/Http/Responders/ResourceResponder.php | 2 +- .../Http/Responders/TaxonomiesResponder.php | 2 +- .../src/Http/Responders/UsersResponder.php | 2 +- .../vendor/typerocket/core/src/Http/Route.php | 56 +++++++++++++++++++ .../core/src/Http/RouteCollection.php | 30 ++++++++++ .../typerocket/core/src/Http/Routes.php | 3 +- .../typerocket/core/src/Register/PostType.php | 24 +++----- .../typerocket/core/src/Register/Registry.php | 24 +++++--- .../typerocket/core/src/Utility/Sanitize.php | 15 ++++- 20 files changed, 299 insertions(+), 52 deletions(-) diff --git a/admin-configure.php b/admin-configure.php index b07c5f78..8d7e3072 100644 --- a/admin-configure.php +++ b/admin-configure.php @@ -2,6 +2,7 @@

The TypeRocket Framework 4 WordPress plugin can be further configured in your wp-config.php file.

\ No newline at end of file diff --git a/typerocket-framework.php b/typerocket-framework.php index 952462df..b876cf96 100644 --- a/typerocket-framework.php +++ b/typerocket-framework.php @@ -3,7 +3,7 @@ Plugin Name: TypeRocket Framework 4 Plugin URI: https://typerocket.com/ Description: TypeRocket Framework - A WordPress Framework To Empower Your Development -Version: 4.0.14 +Version: 4.0.15 Author: Robojuice Author URI: https://robojuice.com/ License: GPLv3 or later @@ -21,17 +21,22 @@ class TypeRocket_Framework { function __construct() { tr_auto_loader(); + $updates_off = false; - if( !defined('TR_UPDATES_OFF') ) { + if( defined('TR_UPDATES_OFF') ) { + $updates_off = TR_UPDATES_OFF; + } + + if( !$updates_off ) { new \TypeRocket\Updates\PluginUpdater([ 'slug' => 'typerocket-framework', - 'api_url' => 'https://typerocket.com/plugins/typerocket-framework/' + 'api_url' => 'https://typerocket.com/plugins/typerocket-framework/' ]); } $this->path = plugin_dir_path(__FILE__); define('TR_AUTO_LOADER', '__return_false'); - define('TR_PLUGIN_VERSION', '4.0.14'); + define('TR_PLUGIN_VERSION', '4.0.15'); register_activation_hook( __FILE__, array($this, 'activation') ); add_action('admin_notices', array($this, 'activation_notice') ); add_action('plugins_loaded', array($this, 'plugins_loaded')); diff --git a/typerocket/vendor/typerocket/core/functions/helpers.php b/typerocket/vendor/typerocket/core/functions/helpers.php index 37ef2596..4678c218 100644 --- a/typerocket/vendor/typerocket/core/functions/helpers.php +++ b/typerocket/vendor/typerocket/core/functions/helpers.php @@ -12,6 +12,17 @@ function tr_app( $append ) { } } +if( ! function_exists('tr_response') ) { + /** + * Get Main Response + * + * @return \TypeRocket\Http\Response + */ + function tr_response() { + return \TypeRocket\Core\Injector::findOrNewSingleton(\TypeRocket\Http\Response::class);; + } +} + if( ! function_exists('tr_assets_url') ) { /** * Get Assets URL @@ -813,6 +824,45 @@ function tr_route() } } +if ( ! function_exists('tr_routes_repo')) { + /** + * Get Routes Repo + * + * @return \TypeRocket\Http\RouteCollection + */ + function tr_routes_repo() + { + return \TypeRocket\Core\Injector::resolve(\TypeRocket\Http\RouteCollection::class); + } +} + +if ( ! function_exists('tr_route_lookup')) { + /** + * Get Routes Repo + * @param string $name + * @return null|\TypeRocket\Http\Route + */ + function tr_route_lookup($name) + { + return tr_routes_repo()->getNamedRoute($name); + } +} + +if ( ! function_exists('tr_route_url_lookup')) { + /** + * Get Routes Repo + * @param string $name + * @param array $values + * @param bool $site + * + * @return null|string + */ + function tr_route_url_lookup($name, $values = [], $site = true) + { + return tr_route_lookup($name)->buildUrlFromPattern($values, $site); + } +} + if ( ! function_exists('tr_query')) { /** * Database Query @@ -830,7 +880,7 @@ function tr_query() * Http Response * * @param string $returned the constant variable name - * @param null|mixed $response The default value + * @param null|\TypeRocket\Http\Response $response The default value * * @return mixed */ diff --git a/typerocket/vendor/typerocket/core/src/Core/Injector.php b/typerocket/vendor/typerocket/core/src/Core/Injector.php index 8ba7f910..1a389c55 100644 --- a/typerocket/vendor/typerocket/core/src/Core/Injector.php +++ b/typerocket/vendor/typerocket/core/src/Core/Injector.php @@ -41,14 +41,57 @@ public static function resolve($class_name) { * @param string $class_name * @param callable $callback * @param bool $singleton + * + * @return bool */ public static function register($class_name, $callback, $singleton = false) { + if(!empty(self::$list[$class_name])) { + return false; + } + self::$list[$class_name] = [ 'callback' => $callback, 'make_singleton' => $singleton, 'singleton_instance' => null ]; + + return true; + } + + /** + * Resolve Singleton + * + * @param string $class_name + * + * @return mixed|null + */ + public static function findOrNewSingleton($class_name) + { + self::register($class_name, function() use ($class_name) { + return new $class_name; + }, true); + + return self::resolve($class_name); + } + + /** + * Destroy By Key + * + * @param string $class_name + * + * @return bool + */ + public static function destroy($class_name) + { + if(array_key_exists($class_name, self::$list)) { + unset(self::$list[$class_name]['singleton_instance']); + unset(self::$list[$class_name]); + + return true; + } + + return false; } } \ No newline at end of file diff --git a/typerocket/vendor/typerocket/core/src/Database/ResultsMeta.php b/typerocket/vendor/typerocket/core/src/Database/ResultsMeta.php index 017b6979..ed6ab2df 100644 --- a/typerocket/vendor/typerocket/core/src/Database/ResultsMeta.php +++ b/typerocket/vendor/typerocket/core/src/Database/ResultsMeta.php @@ -4,6 +4,8 @@ namespace TypeRocket\Database; +use TypeRocket\Models\Contract\Formable; + class ResultsMeta extends Results { protected $storedValues = []; @@ -47,6 +49,14 @@ public function initKeyStore() return $this->storedValues; } + /** + * Get Form Fields + */ + public function getFormFields() + { + return $this->storedValues; + } + /** * Get an attribute from the model. * diff --git a/typerocket/vendor/typerocket/core/src/Elements/Fields/Field.php b/typerocket/vendor/typerocket/core/src/Elements/Fields/Field.php index bedd5a56..478ec414 100644 --- a/typerocket/vendor/typerocket/core/src/Elements/Fields/Field.php +++ b/typerocket/vendor/typerocket/core/src/Elements/Fields/Field.php @@ -73,6 +73,13 @@ public function __toString() return $string; } + /** + * Set Cast + * + * @param callable $callback + * @param array $args + * @return $this + */ public function setCast($callback, array $args = []) { $this->cast = [ @@ -83,6 +90,12 @@ public function setCast($callback, array $args = []) return $this; } + /** + * Get Cast + * + * @param $value + * @return mixed + */ public function getCast($value) { if( is_array($this->cast) && is_callable($this->cast['callback']) ) { @@ -263,7 +276,12 @@ public function getType() */ public function setName( $name ) { - $this->name = Sanitize::underscore( $name ); + $name_parts = explode('.', strrev($name), 2); + $this->name = Sanitize::underscore( strrev($name_parts[0]) ); + + if(!empty($name_parts[1])) { + $this->appendToGroup( strrev($name_parts[1]) ); + } return $this; } diff --git a/typerocket/vendor/typerocket/core/src/Elements/Form.php b/typerocket/vendor/typerocket/core/src/Elements/Form.php index 83d24590..0555b765 100644 --- a/typerocket/vendor/typerocket/core/src/Elements/Form.php +++ b/typerocket/vendor/typerocket/core/src/Elements/Form.php @@ -2,11 +2,14 @@ namespace TypeRocket\Elements; use TypeRocket\Core\Config; +use TypeRocket\Core\Injector; use TypeRocket\Elements\Fields\Submit; use TypeRocket\Elements\Traits\MacroTrait; use TypeRocket\Html\Generator; use TypeRocket\Html\Tag; use TypeRocket\Elements\Fields\Field; +use TypeRocket\Http\ApplicationRoutes; +use TypeRocket\Http\RouteCollection; use TypeRocket\Models\WPComment; use TypeRocket\Models\WPOption; use TypeRocket\Models\WPPost; @@ -37,7 +40,6 @@ class Form * @param string $action update or create * @param null|int $itemId you can set this to null or an integer * @param null|Model|string $model - * @throws \Exception */ public function __construct( $resource = 'auto', $action = 'update', $itemId = null, $model = null ) { @@ -63,7 +65,6 @@ public function __construct( $resource = 'auto', $action = 'update', $itemId = n * @param Model|string $model * * @return $this - * @throws \Exception */ public function setModel( $model ) { @@ -227,18 +228,45 @@ public function useJson($resource = null) * * @param string $method * @param string $url + * @param bool $home * - * @return $this + * @return Form $this */ - public function useUrl($method, $url) + public function useUrl($method, $url, $home = true) { - $url_parts = explode('/', trim($url, '/') ); - $this->formUrl = home_url(implode('/', $url_parts ) . '/', get_http_protocol() ); - $this->method = strtoupper($method); + $this->formUrl = $home ? home_url( trim($url, '/') . '/', get_http_protocol() ) : $url; + $this->method = $method ? strtoupper($method) : $this->method; return $this; } + /** + * @param string $name + * @param null|array $values + * @param null|string $method + * + * @return Form + */ + public function useRoute($name, $values = null, $method = null) + { + /** @var ApplicationRoutes $routes */ + $routes = Injector::resolve(RouteCollection::class); + $located = $routes->getNamedRoute($name); + + $url = $located->buildUrlFromPattern($values ?? $this->model->getProperties()); + return $this->useUrl($method, $url, false); + } + + /** + * Get Form URL + * + * @return mixed + */ + public function getFormUrl() + { + return $this->formUrl; + } + /** * To Admin URL * diff --git a/typerocket/vendor/typerocket/core/src/Elements/Traits/FormConnectorTrait.php b/typerocket/vendor/typerocket/core/src/Elements/Traits/FormConnectorTrait.php index bdaa348f..81314692 100644 --- a/typerocket/vendor/typerocket/core/src/Elements/Traits/FormConnectorTrait.php +++ b/typerocket/vendor/typerocket/core/src/Elements/Traits/FormConnectorTrait.php @@ -2,6 +2,8 @@ namespace TypeRocket\Elements\Traits; +use TypeRocket\Utility\Sanitize; + trait FormConnectorTrait { @@ -90,7 +92,8 @@ public function getGroup() */ public function appendToGroup($append) { - $this->group = $this->group . '.' . $append; + $append = Sanitize::underscore($append, true); + $this->group = $this->group ? $this->group . '.' . $append : $append; return $this; } diff --git a/typerocket/vendor/typerocket/core/src/Elements/Traits/OptionsTrait.php b/typerocket/vendor/typerocket/core/src/Elements/Traits/OptionsTrait.php index 33437373..ecde7366 100644 --- a/typerocket/vendor/typerocket/core/src/Elements/Traits/OptionsTrait.php +++ b/typerocket/vendor/typerocket/core/src/Elements/Traits/OptionsTrait.php @@ -26,7 +26,7 @@ public function setOption( $key, $value ) /** * Set all options * - * @param string $options + * @param array $options * @param string $style options include standard, flat, flip * * @return $this diff --git a/typerocket/vendor/typerocket/core/src/Http/Responders/CommentsResponder.php b/typerocket/vendor/typerocket/core/src/Http/Responders/CommentsResponder.php index 41bf6a3d..05f0ac29 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Responders/CommentsResponder.php +++ b/typerocket/vendor/typerocket/core/src/Http/Responders/CommentsResponder.php @@ -3,7 +3,6 @@ use TypeRocket\Http\Handler; use \TypeRocket\Http\Request; -use \TypeRocket\Http\Response; class CommentsResponder extends Responder { @@ -18,7 +17,7 @@ public function respond( $args ) { $controller = tr_app("Controllers\\CommentController"); $controller = apply_filters('tr_comments_responder_controller', $controller); $request = new Request('PUT', $this->hook); - $response = (new Response())->blockFlash(); + $response = tr_response()->blockFlash(); $handler = (new Handler()) ->setAction('update') diff --git a/typerocket/vendor/typerocket/core/src/Http/Responders/PostsResponder.php b/typerocket/vendor/typerocket/core/src/Http/Responders/PostsResponder.php index 35e37db9..de536cab 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Responders/PostsResponder.php +++ b/typerocket/vendor/typerocket/core/src/Http/Responders/PostsResponder.php @@ -37,7 +37,7 @@ public function respond( $args ) $controller = apply_filters('tr_posts_responder_controller', $controller); $resource = $registered[0] ?? 'post'; - $response = (new Response())->blockFlash(); + $response = tr_response()->blockFlash(); $request = new Request('PUT', $this->hook); $middlewareGroup = [ $resource ,'post']; diff --git a/typerocket/vendor/typerocket/core/src/Http/Responders/ResourceResponder.php b/typerocket/vendor/typerocket/core/src/Http/Responders/ResourceResponder.php index 253f595e..ca5fda1e 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Responders/ResourceResponder.php +++ b/typerocket/vendor/typerocket/core/src/Http/Responders/ResourceResponder.php @@ -24,7 +24,7 @@ class ResourceResponder extends Responder public function respond( $args ) { $request = new Request(null, $this->hook, $this->rest, $this->custom); - $response = new Response(); + $response = tr_response(); $handler = (new Handler()) ->setAction($this->action) diff --git a/typerocket/vendor/typerocket/core/src/Http/Responders/TaxonomiesResponder.php b/typerocket/vendor/typerocket/core/src/Http/Responders/TaxonomiesResponder.php index 9f495853..e031e0be 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Responders/TaxonomiesResponder.php +++ b/typerocket/vendor/typerocket/core/src/Http/Responders/TaxonomiesResponder.php @@ -31,7 +31,7 @@ public function respond( $args ) $controller = apply_filters('tr_taxonomies_responder_controller', $controller); $resource = $registered[0] ?? 'category'; - $response = (new Response())->blockFlash(); + $response = tr_response()->blockFlash(); $request = new Request( 'PUT', $this->hook ); $middlewareGroup = [$resource, 'term', 'category', 'tag']; diff --git a/typerocket/vendor/typerocket/core/src/Http/Responders/UsersResponder.php b/typerocket/vendor/typerocket/core/src/Http/Responders/UsersResponder.php index ab80ad48..2d1bc49a 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Responders/UsersResponder.php +++ b/typerocket/vendor/typerocket/core/src/Http/Responders/UsersResponder.php @@ -18,7 +18,7 @@ public function respond( $args ) { $controller = tr_app("Controllers\\UserController"); $controller = apply_filters('tr_users_responder_controller', $controller); $request = new Request('PUT', $this->hook); - $response = (new Response())->blockFlash(); + $response = tr_response()->blockFlash(); $handler = (new Handler()) ->setAction('update') diff --git a/typerocket/vendor/typerocket/core/src/Http/Route.php b/typerocket/vendor/typerocket/core/src/Http/Route.php index 9f8ba088..ea7d0d8e 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Route.php +++ b/typerocket/vendor/typerocket/core/src/Http/Route.php @@ -7,6 +7,9 @@ class Route { public $match; + public $name; + public $pattern; + public $registeredNamedRoute = false; public $do; public $middleware; public $methods; @@ -146,6 +149,59 @@ public function any() return $this; } + /** + * Name Route + * + * @param string $name my.custom.route.name + * @param string $pattern url-path/:id/create + * @param null|RouteCollection $routes + * @return $this + */ + public function name($name, $pattern = null, $routes = null) + { + if(!$this->registeredNamedRoute) { + $this->name = $name; + $this->pattern = $pattern; + + /** @var RouteCollection $routes */ + $routes = $routes instanceof RouteCollection ? $routes : Injector::resolve(RouteCollection::class); + $routes->registerNamedRoute($this); + } + + return $this; + } + + /** + * Build Url From Pattern + * + * @param array $values + * @param bool $site + * @return mixed + */ + public function buildUrlFromPattern(array $values = [], $site = true) + { + $pattern = $this->pattern; + + if(!$pattern) { + $keys = array_map(function($value) { + return strtolower($value[0] == ':' ? $value : ':' . $value); + }, $this->match[1]); + + $match = array_map(function($v) { return '/\(.+\)/U'; }, $keys); + $pattern = preg_replace($match, $keys, $this->match[0] ?? null, 1); + } + + $keys = array_keys($values); + + $keys = array_map(function($value) { + return strtolower($value[0] == ':' ? $value : ':' . $value); + }, $keys); + + $built = str_replace($keys, $values, $pattern); + + return $site ? site_url( ltrim($built, '/') ) : $built; + } + /** * Register the route * diff --git a/typerocket/vendor/typerocket/core/src/Http/RouteCollection.php b/typerocket/vendor/typerocket/core/src/Http/RouteCollection.php index 5e0d5513..15c5555a 100644 --- a/typerocket/vendor/typerocket/core/src/Http/RouteCollection.php +++ b/typerocket/vendor/typerocket/core/src/Http/RouteCollection.php @@ -13,6 +13,7 @@ abstract class RouteCollection { public $routes = []; + protected $named = []; /** * Add Route @@ -22,11 +23,29 @@ abstract class RouteCollection */ public function addRoute( $route ) { + $this->registerNamedRoute($route); + $this->routes[] = $route; return $this; } + /** + * Register Named Route + * + * @param Route|null $route + * @return $this + */ + public function registerNamedRoute($route) + { + if($route->name && empty($this->named[$route->name]) ) { + $this->named[$route->name] = $route; + $route->registeredNamedRoute = true; + } + + return $this; + } + /** * Count Routes * @@ -57,4 +76,15 @@ public function getRegisteredRoutes($method) return $routesRegistered; } + + /** + * Get Named Route + * + * @param $name + * @return Route|null + */ + public function getNamedRoute($name) + { + return $this->named[$name] ?? null; + } } \ No newline at end of file diff --git a/typerocket/vendor/typerocket/core/src/Http/Routes.php b/typerocket/vendor/typerocket/core/src/Http/Routes.php index 15e88432..87e53505 100644 --- a/typerocket/vendor/typerocket/core/src/Http/Routes.php +++ b/typerocket/vendor/typerocket/core/src/Http/Routes.php @@ -131,8 +131,7 @@ private function runRoute($path = null, $handle = null, $wilds = null) } if (is_callable($handle->do)) { - $response = new Response(); - $args[2]['response'] = $response; + $args[2]['response'] = tr_response(); $map = resolve_method_args($handle->do, $args[2]); tr_http_response(resolve_method_map($map), $args[2]['response']); } else { diff --git a/typerocket/vendor/typerocket/core/src/Register/PostType.php b/typerocket/vendor/typerocket/core/src/Register/PostType.php index 48245caa..888d2584 100644 --- a/typerocket/vendor/typerocket/core/src/Register/PostType.php +++ b/typerocket/vendor/typerocket/core/src/Register/PostType.php @@ -392,22 +392,6 @@ public function getSlug() return $this->args['rewrite']['slug']; } - /** - * Set Root Slug - * - * Force slug to use the base URL instead of the archive page. - * This will not disabled the archive page for the post type. - * - * @return PostType $this - */ - public function setRootSlugNoConflict() - { - $this->args['rewrite']['with_front'] = false; - $this->rootSlug = true; - - return $this; - } - /** * Get Root Slug * @@ -645,7 +629,13 @@ public function setAdminOnly() { */ public function setRootOnly() { - return $this->setRootSlugNoConflict()->disableArchivePage(); + $this->setArgument('publicly_queryable', true); + $this->setArgument('query_var', true); + $this->setArgument('rewrite', false); + $this->disableArchivePage(); + $this->rootSlug = true; + + return $this; } /** diff --git a/typerocket/vendor/typerocket/core/src/Register/Registry.php b/typerocket/vendor/typerocket/core/src/Register/Registry.php index 8b9bb916..9bdf6b53 100644 --- a/typerocket/vendor/typerocket/core/src/Register/Registry.php +++ b/typerocket/vendor/typerocket/core/src/Register/Registry.php @@ -477,6 +477,8 @@ public static function setPostTypeColumns( PostType $post_type) */ public static function setAggregatePostTypeHooks() { + global $wp_rewrite; + /** * Post Type Hooks */ @@ -493,28 +495,32 @@ public static function setAggregatePostTypeHooks() if($root_slugs) { add_filter( 'post_type_link', function ( $post_link, $post ) use ($root_slugs) { - if ( in_array($post->post_type, $root_slugs) && 'publish' === $post->post_status ) { - $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link ); + if ( in_array($post->post_type, $root_slugs) ) { + $post_link = str_replace( '?' . $post->post_type . '=', '', $post_link ); } return $post_link; }, 10, 2 ); add_action( 'pre_get_posts', function ( $query ) use ($root_slugs) { + global $wpdb; + /** @var WP_Query $query */ - if ( ! $query->is_main_query() ) { + if ( ! $query->is_main_query() || empty( $query->query['name'] ) ) { return; } - if ( ! isset( $query->query['page'] ) || 2 !== count( $query->query ) ) { + if (! isset($query->query['feed']) && ( ! isset( $query->query['page'] ) || 2 !== count( $query->query ) ) ) { return; } - if ( empty( $query->query['name'] ) ) { - return; + $types = "'" . implode("','", $root_slugs) . "'"; + $check_sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ({$types}) AND post_name = %s AND post_status IN ('publish','private') LIMIT 1"; + + if( $wpdb->get_var( $wpdb->prepare( $check_sql, $query->query['name'] ) ) ) { + $query->set( 'post_type', $root_slugs ); } - $query->set( 'post_type', array_merge(['post', 'page'], $root_slugs) ); - } ); + }); add_filter('wp_unique_post_slug', function($slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug) use ($root_slugs) { global $wpdb, $wp_rewrite; @@ -522,7 +528,7 @@ public static function setAggregatePostTypeHooks() $post_types = array_merge(['post', 'page'], $root_slugs); $types = "'" . implode("','", $post_types) . "'"; - if ( in_array($post_type, ['symbol', 'post', 'page']) || in_array( $slug, $wp_rewrite->feeds ) || 'embed' === $slug || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) { + if ( in_array($post_type, $post_types) || in_array( $slug, $wp_rewrite->feeds ) || 'embed' === $slug || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) { $suffix = 2; $check_sql = "SELECT post_name FROM {$wpdb->posts} WHERE post_type IN ({$types}) AND post_name = %s AND ID != %d LIMIT 1"; do { diff --git a/typerocket/vendor/typerocket/core/src/Utility/Sanitize.php b/typerocket/vendor/typerocket/core/src/Utility/Sanitize.php index f8828732..600e1499 100644 --- a/typerocket/vendor/typerocket/core/src/Utility/Sanitize.php +++ b/typerocket/vendor/typerocket/core/src/Utility/Sanitize.php @@ -130,14 +130,23 @@ public static function hex( $hex, $default = '#000000' ) * ` --"2_ _e''X AM!pl'e-"-1_@` -> _2_ex_ample_1_ * * @param string $name + * @param bool $keep_dots * * @return mixed|string */ - public static function underscore( $name ) + public static function underscore( $name, $keep_dots = false ) { if (is_string( $name )) { - $name = preg_replace( '/[\.]+/', '_', $name ); - $name = preg_replace("/[^A-Za-z0-9\\s\\-\\_?]/",'', strtolower(trim($name)) ); + + if($keep_dots) { + $name = preg_replace( '/[\.]+/', '.', $name ); + $name = preg_replace("/[^A-Za-z0-9\.\\s\\-\\_?]/",'', strtolower(trim($name)) ); + } else { + $name = preg_replace( '/[\.]+/', '_', $name ); + $name = preg_replace("/[^A-Za-z0-9\\s\\-\\_?]/",'', strtolower(trim($name)) ); + } + + $name = preg_replace( '/[-\\s]+/', '_', $name ); $name = preg_replace( '/_+/', '_', $name ); }