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