<?php
/**
 * Postomatic Plugin - This file handles automatic
 * class loading for the Postomatic plugin.
 *
 *  PHP Version 5.6
 *
 * @package  Postomatic
 * @category Plugin
 * @license  GPL-2.0-or-later https://www.gnu.org/licenses/gpl-2.0.html
 * @link     https://buildomatics.com/postomatics
 * @since    1.0.0
 */

namespace Postomatic;

/**
 * Autoload Plugin Classes.
 *
 * Implements a secure autoloading mechanism for plugin classes.
 *
 * @param string $class_name Fully qualified class name.
 *
 * @return void
 */
spl_autoload_register(
	function ( $class_name ) {
		// Only handle classes in our namespace.
		if ( 0 !== strpos( $class_name, 'Postomatic\\' ) ) {
			return;
		}

		// Sanitize and validate class name.
		$relative_class = substr( $class_name, strlen( 'Postomatic\\' ) );

		// Strict validation of class name.
		if ( ! preg_match( '/^[a-zA-Z0-9_\\\\]+$/', $relative_class ) ) {
			return;
		}

		// Prevent potential directory traversal.
		$class_path = str_replace(
			array( '\\', '../', '..\\' ),
			array( '/', '', '' ),
			$relative_class
		);

		// Determine file path based on namespace.
		$file_mappings = array(
			'Core/'     => 'includes/core/class-',
			'Admin/'    => 'includes/admin/class-',
			'Api/'      => 'includes/api/class-',
			'Frontend/' => 'includes/public/class-',
			''          => 'includes/class-',
		);

		$file_path = '';
		foreach ( $file_mappings as $namespace => $path_prefix ) {
			if ( 0 === strpos( $class_path, $namespace ) ) {
				$file_path = POSTOMATIC_PLUGIN_DIR . $path_prefix .
				strtolower(
					preg_replace_callback(
						array( '/([a-z])([A-Z])/', '/(_)/' ),  // Match cases.
						function ( $matches ) {
							return isset( $matches[2] )
							? $matches[1]
							. '-'
							. strtolower( $matches[2] )  // camelCase.
							: '-';  // underscore.
						},
						str_replace( $namespace, '', $class_path )
					)
				) . '.php';
				break;
			}
		}

		// Additional security checks.
		$real_file       = realpath( $file_path );
		$real_plugin_dir = realpath( POSTOMATIC_PLUGIN_DIR );

		if ( $real_file
			&& 0 === strpos( $real_file, $real_plugin_dir )
			&& file_exists( $real_file )
		) {
			include_once $real_file;
		}
	}
);
