first commit
This commit is contained in:
317
system/engine/loader.php
Normal file
317
system/engine/loader.php
Normal file
@ -0,0 +1,317 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Engine;
|
||||
/**
|
||||
* Class Loader
|
||||
*/
|
||||
class Loader {
|
||||
/**
|
||||
* @var object|\Opencart\System\Engine\Registry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->registry = $registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* __get
|
||||
*
|
||||
* https://www.php.net/manual/en/language.oop5.overloading.php#object.get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function __get(string $key): object {
|
||||
return $this->registry->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* __set
|
||||
*
|
||||
* https://www.php.net/manual/en/language.oop5.overloading.php#object.set
|
||||
*
|
||||
* @param string $key
|
||||
* @param object $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set(string $key, object $value): void {
|
||||
$this->registry->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller
|
||||
*
|
||||
* https://wiki.php.net/rfc/variadics
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function controller(string $route, mixed ...$args): mixed {
|
||||
// Sanitize the call
|
||||
$route = preg_replace('/[^a-zA-Z0-9_|\/\.]/', '', str_replace('|', '.', $route));
|
||||
|
||||
$output = '';
|
||||
|
||||
// Keep the original trigger
|
||||
$action = new \Opencart\System\Engine\Action($route);
|
||||
|
||||
while ($action) {
|
||||
$route = $action->getId();
|
||||
|
||||
// Trigger the pre events
|
||||
$result = $this->event->trigger('controller/' . $route . '/before', [&$route, &$args]);
|
||||
|
||||
if ($result instanceof \Opencart\System\Engine\Action) {
|
||||
$action = $result;
|
||||
}
|
||||
|
||||
// Execute action
|
||||
$result = $action->execute($this->registry, $args);
|
||||
|
||||
// Make action a non-object so it's not infinitely looping
|
||||
$action = '';
|
||||
|
||||
// Action object returned then we keep the loop going
|
||||
if ($result instanceof \Opencart\System\Engine\Action) {
|
||||
$action = $result;
|
||||
}
|
||||
|
||||
// If not an object then it's the output
|
||||
if (!$action) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
// Trigger the post events
|
||||
$result = $this->event->trigger('controller/' . $route . '/after', [&$route, &$args, &$output]);
|
||||
|
||||
if ($result instanceof \Opencart\System\Engine\Action) {
|
||||
$action = $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model
|
||||
*
|
||||
* @param string $route
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function model(string $route): void {
|
||||
// Sanitize the call
|
||||
$route = preg_replace('/[^a-zA-Z0-9_\/]/', '', $route);
|
||||
|
||||
// Converting a route path to a class name
|
||||
$class = 'Opencart\\' . $this->config->get('application') . '\Model\\' . str_replace(['_', '/'], ['', '\\'], ucwords($route, '_/'));
|
||||
|
||||
// Create a key to store the model object
|
||||
$key = 'model_' . str_replace('/', '_', $route);
|
||||
|
||||
// Check if the requested model is already stored in the registry.
|
||||
if (!$this->registry->has($key)) {
|
||||
if (class_exists($class)) {
|
||||
$model = new $class($this->registry);
|
||||
|
||||
$proxy = new \Opencart\System\Engine\Proxy();
|
||||
|
||||
foreach (get_class_methods($model) as $method) {
|
||||
if ((substr($method, 0, 2) != '__') && is_callable($class, $method)) {
|
||||
// Grab args using function because we don't know the number of args being passed.
|
||||
// https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
|
||||
// https://wiki.php.net/rfc/variadics
|
||||
$proxy->{$method} = function (mixed &...$args) use ($route, $model, $method): mixed {
|
||||
$route = $route . '/' . $method;
|
||||
|
||||
$output = '';
|
||||
|
||||
// Trigger the pre events
|
||||
$result = $this->event->trigger('model/' . $route . '/before', [&$route, &$args]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
if (!$output) {
|
||||
// Get the method to be used
|
||||
$callable = [$model, $method];
|
||||
|
||||
if (is_callable($callable)) {
|
||||
$output = call_user_func_array($callable, $args);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not call model/' . $route . '!');
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the post events
|
||||
$result = $this->event->trigger('model/' . $route . '/after', [&$route, &$args, &$output]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
return $output;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$this->registry->set($key, $proxy);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load model ' . $class . '!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View
|
||||
*
|
||||
* Loads the template file and generates the html code.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $data
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function view(string $route, array $data = [], string $code = ''): string {
|
||||
// Sanitize the call
|
||||
$route = preg_replace('/[^a-zA-Z0-9_\/]/', '', $route);
|
||||
|
||||
$output = '';
|
||||
|
||||
// Trigger the pre events
|
||||
$result = $this->event->trigger('view/' . $route . '/before', [&$route, &$data, &$code]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
if (!$output) {
|
||||
// Make sure it's only the last event that returns an output if required.
|
||||
$output = $this->template->render($route, $data, $code);
|
||||
}
|
||||
|
||||
// Trigger the post events
|
||||
$result = $this->event->trigger('view/' . $route . '/after', [&$route, &$data, &$output]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* @param string $route
|
||||
* @param string $prefix
|
||||
* @param string $code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function language(string $route, string $prefix = '', string $code = ''): array {
|
||||
// Sanitize the call
|
||||
$route = preg_replace('/[^a-zA-Z0-9_\-\/]/', '', $route);
|
||||
|
||||
$output = [];
|
||||
|
||||
// Trigger the pre events
|
||||
$result = $this->event->trigger('language/' . $route . '/before', [&$route, &$prefix, &$code]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
if (!$output) {
|
||||
$output = $this->language->load($route, $prefix, $code);
|
||||
}
|
||||
|
||||
// Trigger the post events
|
||||
$result = $this->event->trigger('language/' . $route . '/after', [&$route, &$prefix, &$code, &$output]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Config
|
||||
*
|
||||
* @param string $route
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function config(string $route): array {
|
||||
// Sanitize the call
|
||||
$route = preg_replace('/[^a-zA-Z0-9_\-\/]/', '', $route);
|
||||
|
||||
$output = [];
|
||||
|
||||
// Trigger the pre events
|
||||
$result = $this->event->trigger('config/' . $route . '/before', [&$route]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
if (!$output) {
|
||||
$output = $this->config->load($route);
|
||||
}
|
||||
|
||||
// Trigger the post events
|
||||
$result = $this->event->trigger('config/' . $route . '/after', [&$route, &$output]);
|
||||
|
||||
if ($result) {
|
||||
$output = $result;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper
|
||||
*
|
||||
* @param string $route
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function helper(string $route): void {
|
||||
$route = preg_replace('/[^a-zA-Z0-9_\/]/', '', $route);
|
||||
|
||||
if (!str_starts_with($route, 'extension/')) {
|
||||
$file = DIR_SYSTEM . 'helper/' . $route . '.php';
|
||||
} else {
|
||||
$parts = explode('/', substr($route, 10));
|
||||
|
||||
$code = array_shift($parts);
|
||||
|
||||
$file = DIR_EXTENSION . $code . '/system/helper/' . implode('/', $parts) . '.php';
|
||||
}
|
||||
|
||||
if (is_file($file)) {
|
||||
include_once($file);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load helper ' . $route . '!');
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user