docs/api/source-system.engine.loader.html
| 1: | <?php |
| 2: | /** |
| 3: | * @package OpenCart |
| 4: | * |
| 5: | * @author Daniel Kerr |
| 6: | * @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/) |
| 7: | * @license https://opensource.org/licenses/GPL-3.0 |
| 8: | * |
| 9: | * @see https://www.opencart.com |
| 10: | */ |
| 11: | namespace Opencart\System\Engine; |
| 12: | /** |
| 13: | * Class Loader |
| 14: | * |
| 15: | * @mixin \Opencart\System\Engine\Registry |
| 16: | */ |
| 17: | class Loader { |
| 18: | /** |
| 19: | * @var \Opencart\System\Engine\Registry |
| 20: | */ |
| 21: | protected \Opencart\System\Engine\Registry $registry; |
| 22: | |
| 23: | /** |
| 24: | * Constructor |
| 25: | * |
| 26: | * @param \Opencart\System\Engine\Registry $registry |
| 27: | */ |
| 28: | public function __construct(\Opencart\System\Engine\Registry $registry) { |
| 29: | $this->registry = $registry; |
| 30: | } |
| 31: | |
| 32: | /** |
| 33: | * __get |
| 34: | * |
| 35: | * https://www.php.net/manual/en/language.oop5.overloading.php#object.get |
| 36: | * |
| 37: | * @param string $key |
| 38: | * |
| 39: | * @return object |
| 40: | */ |
| 41: | public function __get(string $key): object { |
| 42: | return $this->registry->get($key); |
| 43: | } |
| 44: | |
| 45: | /** |
| 46: | * __set |
| 47: | * |
| 48: | * https://www.php.net/manual/en/language.oop5.overloading.php#object.set |
| 49: | * |
| 50: | * @param string $key |
| 51: | * @param object $value |
| 52: | * |
| 53: | * @return void |
| 54: | */ |
| 55: | public function __set(string $key, object $value): void { |
| 56: | $this->registry->set($key, $value); |
| 57: | } |
| 58: | |
| 59: | /** |
| 60: | * Controller |
| 61: | * |
| 62: | * https://wiki.php.net/rfc/variadics |
| 63: | * |
| 64: | * @param string $route |
| 65: | * @param mixed $args |
| 66: | * |
| 67: | * @return mixed |
| 68: | */ |
| 69: | public function controller(string $route, ...$args) { |
| 70: | // Sanitize the call |
| 71: | $route = preg_replace('/[^a-zA-Z0-9_|/.]/', '', str_replace('|', '.', $route)); |
| 72: | |
| 73: | $trigger = $route; |
| 74: | |
| 75: | // Trigger the pre events |
| 76: | $this->event->trigger('controller/' . $trigger . '/before', [&$route, &$args]); |
| 77: | |
| 78: | // Keep the original trigger |
| 79: | $action = new \Opencart\System\Engine\Action($route); |
| 80: | |
| 81: | while ($action) { |
| 82: | // Execute action |
| 83: | $output = $action->execute($this->registry, $args); |
| 84: | |
| 85: | // Make action a non-object so it's not infinitely looping |
| 86: | $action = ''; |
| 87: | |
| 88: | // Action object returned then we keep the loop going |
| 89: | if ($output instanceof \Opencart\System\Engine\Action) { |
| 90: | $action = $output; |
| 91: | } |
| 92: | } |
| 93: | |
| 94: | // Trigger the post events |
| 95: | $this->event->trigger('controller/' . $trigger . '/after', [&$route, &$args, &$output]); |
| 96: | |
| 97: | return $output; |
| 98: | } |
| 99: | |
| 100: | /** |
| 101: | * Model |
| 102: | * |
| 103: | * @param string $route |
| 104: | * |
| 105: | * @return void |
| 106: | */ |
| 107: | public function model(string $route): void { |
| 108: | // Sanitize the call |
| 109: | $route = preg_replace('/[^a-zA-Z0-9_/]/', '', $route); |
| 110: | |
| 111: | // Create a new key to store the model object |
| 112: | $key = 'model_' . str_replace('/', '_', $route); |
| 113: | |
| 114: | if (!$this->registry->has($key)) { |
| 115: | // Converting a route path to a class name |
| 116: | $class = 'Opencart\' . $this->config->get('application') . '\Model\' . str_replace(['_', '/'], ['', '\'], ucwords($route, '_/')); |
| 117: | |
| 118: | if (class_exists($class)) { |
| 119: | $proxy = new \Opencart\System\Engine\Proxy(); |
| 120: | |
| 121: | foreach (get_class_methods($class) as $method) { |
| 122: | $reflection = new \ReflectionMethod($class, $method); |
| 123: | |
| 124: | if ((substr($method, 0, 2) != '__') && $reflection->isPublic()) { |
| 125: | // https://wiki.php.net/rfc/variadics |
| 126: | $proxy->{$method} = function(&...$args) use ($route, $method) { |
| 127: | $route = $route . '/' . $method; |
| 128: | |
| 129: | $trigger = $route; |
| 130: | |
| 131: | // Trigger the pre events |
| 132: | $this->event->trigger('model/' . $trigger . '/before', [&$route, &$args]); |
| 133: | |
| 134: | // Find last / so we can remove and find the method |
| 135: | $pos = strrpos($route, '/'); |
| 136: | |
| 137: | $class = substr($route, 0, $pos); |
| 138: | $method = substr($route, $pos + 1); |
| 139: | |
| 140: | // Create a new key to store the model object |
| 141: | $key = 'callback_' . str_replace('/', '_', $class); |
| 142: | |
| 143: | if (!$this->registry->has($key)) { |
| 144: | // Initialize the class |
| 145: | $model = $this->factory->model($class); |
| 146: | |
| 147: | // Store object |
| 148: | $this->registry->set($key, $model); |
| 149: | } else { |
| 150: | $model = $this->registry->get($key); |
| 151: | } |
| 152: | |
| 153: | $callable = [$model, $method]; |
| 154: | |
| 155: | if (is_callable($callable)) { |
| 156: | $output = $callable(...$args); |
| 157: | } else { |
| 158: | throw new \Exception('Error: Could not call model/' . $route . '!'); |
| 159: | } |
| 160: | |
| 161: | // Trigger the post events |
| 162: | $this->event->trigger('model/' . $trigger . '/after', [&$route, &$args, &$output]); |
| 163: | |
| 164: | return $output; |
| 165: | }; |
| 166: | } |
| 167: | } |
| 168: | |
| 169: | $this->registry->set($key, $proxy); |
| 170: | } else { |
| 171: | throw new \Exception('Error: Could not load model ' . $class . '!'); |
| 172: | } |
| 173: | } |
| 174: | } |
| 175: | |
| 176: | /** |
| 177: | * View |
| 178: | * |
| 179: | * Loads the template file and generates the html code. |
| 180: | * |
| 181: | * @param string $route |
| 182: | * @param array<string, mixed> $data |
| 183: | * @param string $code |
| 184: | * |
| 185: | * @return string |
| 186: | */ |
| 187: | public function view(string $route, array $data = [], string $code = ''): string { |
| 188: | // Sanitize the call |
| 189: | $route = preg_replace('/[^a-zA-Z0-9_/]/', '', $route); |
| 190: | |
| 191: | $trigger = $route; |
| 192: | |
| 193: | $output = ''; |
| 194: | |
| 195: | // Trigger the pre events |
| 196: | $this->event->trigger('view/' . $trigger . '/before', [&$route, &$data, &$code, &$output]); |
| 197: | |
| 198: | if (!$output) { |
| 199: | // Make sure it's only the last event that returns an output if required. |
| 200: | $output = $this->template->render($route, $data, $code); |
| 201: | } |
| 202: | |
| 203: | // Trigger the post events |
| 204: | $this->event->trigger('view/' . $trigger . '/after', [&$route, &$data, &$output]); |
| 205: | |
| 206: | return $output; |
| 207: | } |
| 208: | |
| 209: | /** |
| 210: | * Language |
| 211: | * |
| 212: | * @param string $route |
| 213: | * @param string $prefix |
| 214: | * @param string $code |
| 215: | * |
| 216: | * @return array<string, string> |
| 217: | */ |
| 218: | public function language(string $route, string $prefix = '', string $code = ''): array { |
| 219: | // Sanitize the call |
| 220: | $route = preg_replace('/[^a-zA-Z0-9_-/]/', '', $route); |
| 221: | |
| 222: | $trigger = $route; |
| 223: | |
| 224: | // Trigger the pre events |
| 225: | $this->event->trigger('language/' . $trigger . '/before', [&$route, &$prefix, &$code]); |
| 226: | |
| 227: | $output = $this->language->load($route, $prefix, $code); |
| 228: | |
| 229: | // Trigger the post events |
| 230: | $this->event->trigger('language/' . $trigger . '/after', [&$route, &$prefix, &$code, &$output]); |
| 231: | |
| 232: | return $output; |
| 233: | } |
| 234: | |
| 235: | /** |
| 236: | * Library |
| 237: | * |
| 238: | * @param string $route |
| 239: | * @param array<mixed> $args |
| 240: | * |
| 241: | * @return object |
| 242: | */ |
| 243: | public function library(string $route, &...$args): object { |
| 244: | // Sanitize the call |
| 245: | $route = preg_replace('/[^a-zA-Z0-9_/]/', '', $route); |
| 246: | |
| 247: | // Create a new key to store the model object |
| 248: | $key = 'library_' . str_replace('/', '_', $route); |
| 249: | |
| 250: | if (!$this->registry->has($key)) { |
| 251: | // Initialize the class |
| 252: | $library = $this->factory->library($route, $args); |
| 253: | |
| 254: | // Store object |
| 255: | $this->registry->set($key, $library); |
| 256: | } else { |
| 257: | $library = $this->registry->get($key); |
| 258: | } |
| 259: | |
| 260: | return $library; |
| 261: | } |
| 262: | |
| 263: | /** |
| 264: | * Config |
| 265: | * |
| 266: | * @param string $route |
| 267: | * |
| 268: | * @return array<string, string> |
| 269: | */ |
| 270: | public function config(string $route): array { |
| 271: | // Sanitize the call |
| 272: | $route = preg_replace('/[^a-zA-Z0-9_-/]/', '', $route); |
| 273: | |
| 274: | $trigger = $route; |
| 275: | |
| 276: | // Trigger the pre events |
| 277: | $this->event->trigger('config/' . $trigger . '/before', [&$route]); |
| 278: | |
| 279: | $output = $this->config->load($route); |
| 280: | |
| 281: | // Trigger the post events |
| 282: | $this->event->trigger('config/' . $trigger . '/after', [&$route, &$output]); |
| 283: | |
| 284: | return $output; |
| 285: | } |
| 286: | |
| 287: | /** |
| 288: | * Helper |
| 289: | * |
| 290: | * @param string $route |
| 291: | * |
| 292: | * @return void |
| 293: | */ |
| 294: | public function helper(string $route): void { |
| 295: | $route = preg_replace('/[^a-zA-Z0-9_/]/', '', $route); |
| 296: | |
| 297: | if (!str_starts_with($route, 'extension/')) { |
| 298: | $file = DIR_SYSTEM . 'helper/' . $route . '.php'; |
| 299: | } else { |
| 300: | $parts = explode('/', substr($route, 10)); |
| 301: | |
| 302: | $code = array_shift($parts); |
| 303: | |
| 304: | $file = DIR_EXTENSION . $code . '/system/helper/' . implode('/', $parts) . '.php'; |
| 305: | } |
| 306: | |
| 307: | if (is_file($file)) { |
| 308: | include_once($file); |
| 309: | } else { |
| 310: | throw new \Exception('Error: Could not load helper ' . $route . '!'); |
| 311: | } |
| 312: | } |
| 313: | } |
| 314: | |
OpenCart API API documentation generated by ApiGen dev-master