Skip to content

Instantly share code, notes, and snippets.

@wppunk
Created February 20, 2020 12:23
Show Gist options
  • Save wppunk/02ed08063753e303256c2d5a7357e561 to your computer and use it in GitHub Desktop.
Save wppunk/02ed08063753e303256c2d5a7357e561 to your computer and use it in GitHub Desktop.
Autoload classes, interfaces and traits by namespace prefix
<?php
/**
* Autoload classes, interfaces and traits for your namespaces.
*
* @package Autoload
*/
/**
* Class Autoload
*/
class Autoload {
/**
* Classmap file
*
* @var string
*/
private $map_file;
/**
* Classmap
*
* @var array
*/
private $map;
/**
* Prefix for your namespace
*
* @var string
*/
private $prefix = 'Custom_';
/**
* Has the cache been updated
*
* @var bool
*/
private $has_been_update = false;
/**
* Autoload constructor.
*
* @throws Exception Class|Interface|Trait not found.
*/
public function __construct() {
$this->map_file = __DIR__ . '/classmap.php';
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$this->map = @include $this->map_file;
$this->map = is_array( $this->map ) ? $this->map : [];
spl_autoload_register( [ $this, 'autoload' ] );
add_action( 'shutdown', [ $this, 'update_cache' ] );
}
/**
* Autoload files for custom plugins
*
* @param string $class Full class name.
*/
private function autoload( string $class ): void {
if ( 0 === strpos( $class, $this->prefix ) ) {
if ( $this->map[ $class ] && file_exists( $this->map[ $class ] ) ) {
require_once $this->map[ $class ];
} else {
$this->has_been_update = true;
$plugin_parts = explode( '\\', $class );
$name = array_pop( $plugin_parts );
$name = preg_match( '/^(Interface|Trait)/', $name )
? $name . '.php'
: 'class-' . $name . '.php';
$path = implode( '/', $plugin_parts ) . '/' . $name;
$path = strtolower( str_replace( [ '\\', '_' ], [ '/', '-' ], $path ) );
$path = WP_CONTENT_DIR . '/plugins/' . $path;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$this->map[ $class ] = $path;
require_once $path;
}
}
}
/**
* Create instance WP_Filesystem
*
* @return WP_Filesystem_Direct
*
* phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
*/
private function WP_Filesystem(): WP_Filesystem_Direct {
//phpcs:enable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
global $wp_filesystem;
if ( null === $wp_filesystem ) {
if ( ! class_exists( 'WP_Filesystem_Base' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
}
WP_Filesystem();
}
return new WP_Filesystem_Direct( null );
}
/**
* Update classmap
*/
public function update_cache(): void {
if ( ! $this->has_been_update ) {
return;
}
$map = implode(
"\n",
array_map(
function ( $k, $v ) {
return "'$k' => '$v',";
},
array_keys( $this->map ),
array_values( $this->map )
)
);
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
$filesystem = self::WP_Filesystem();
$filesystem->put_contents( $this->map_file, '<?php return [' . $map . '];' );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment