PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Services / ShortCodeParser / SmartCodeParser.php

SmartCodeParser.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Services/ShortCodeParser/SmartCodeParser.php

266 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\ShortCodeParser;
4
5 use FluentCart\App\App;
6 use FluentCart\Framework\Container\Contracts\BindingResolutionException;
7 use FluentCart\Framework\Foundation\Application;
8 use FluentCart\Framework\Support\Arr;
9 use FluentCart\Framework\Support\Collection;
10
11 class SmartCodeParser
12 {
13
14 use ValueTransformer;
15
16 /**
17 * The application instance.
18 *
19 * @var Application
20 */
21 protected Application $app;
22
23 /**
24 * Configuration instance.
25 *
26 * @var ?Collection
27 */
28 protected ?Collection $config;
29
30 /**
31 * Hook Prefix.
32 *
33 * @var String
34 */
35 protected string $hookPrefix;
36
37 /**
38 * SmartCodeParser constructor.
39 */
40 public function __construct()
41 {
42 $application = App::getInstance();
43 $pluginConfig = $application->make('config')->get('shortcode');
44 $this->app = $application;
45 $this->config = new Collection($pluginConfig);
46 $this->hookPrefix = App::config()->get('hook_prefix');
47 }
48
49 /**
50 * Parses the given code using the appropriate parser class.
51 *
52 * @param string $code
53 * @param array $data
54 * @return string
55 * @throws BindingResolutionException
56 */
57 public function parse(string $code, array $data): ?string
58 {
59 return $this->parseCode($code, $data);
60 }
61
62 /**
63 * Parses the given code using the appropriate parser class.
64 *
65 * @param string $code
66 * @param mixed $data
67 * @return string
68 * @throws BindingResolutionException
69 */
70 public function parseCode(string $code, $data): ?string
71 {
72 $code = trim($code);
73
74 $explodedCode = explode('.', $code);
75 if (count($explodedCode) <= 1) {
76 return apply_filters($this->hookPrefix . 'smartcode_fallback', $code, $data);
77 }
78 $parserReference = $this->getParseHandlerReference($code);
79 $parseHandler = Arr::get($parserReference, 'handler');
80
81 if (!$parseHandler) {
82 return apply_filters($this->hookPrefix . 'smartcode_fallback', $code, $data);
83 }
84
85 $parser = $this->app->makeWith($parseHandler, ['data' => $data]);
86
87 $parsedValue = "";
88
89 if (method_exists($parser, 'parse')) {
90 $parsedValue = $parser->parse(
91 $parserReference['accessor'],
92 $parserReference['template'],
93 $this->evaluateCondition($parserReference['template'])
94 );
95
96 }
97
98 // Parser returned null = accessor not recognised. Give the fallback
99 // filter a chance so dynamic blocks can register handlers for codes
100 // their parser doesn't know about (e.g. PDF item table).
101 if ($parsedValue === null) {
102 $fallback = apply_filters($this->hookPrefix . 'smartcode_fallback', $code, $data);
103 if ($fallback !== $code) {
104 $parsedValue = $fallback;
105 }
106 }
107
108 return $this->transform($parsedValue, $code, $data);
109 }
110
111 /**
112 * Retrieves the appropriate parser class for the given code.
113 *
114 * @param string $code
115 * @return ?string
116 */
117 public function getParserClass(string $code): ?string
118 {
119 $parsers = $this->config->get('parsers');
120 return Arr::get($parsers, $code);
121 }
122
123 /**
124 * Retrieves the parse handler reference for the given template.
125 *
126 * @param string $template
127 * @return array
128 */
129 public function getParseHandlerReference(string $template): array
130 {
131 static $reference = [];
132
133 $parserData = [
134 'parser' => null,
135 'accessor' => null,
136 'template' => $template,
137 'handler' => null,
138 ];
139
140 $templateCode = $this->getReference($template);
141
142 if (!isset($reference[$templateCode])) {
143 if (str_contains($templateCode, '.')) {
144 $parsed = explode($this->config->get('parser_separator'), $templateCode);
145 $parserData['parser'] = $parsed[0];
146 $parserData['accessor'] = implode($this->config->get('parser_separator'), array_slice($parsed, 1));
147 } else {
148 //If no parser is found, GlobalParser class will be called if exist
149 $parserData['parser'] = 'global';
150 $parserData['accessor'] = $templateCode;
151 }
152
153 $parserData['handler'] = $this->getParserClass($parserData['parser']);
154 $reference[$template] = $parserData;
155 }
156 if (!isset($reference[$template]) && isset($reference[$templateCode])) {
157 $reference[$template] = $reference[$templateCode];
158 }
159
160 return $reference[$template];
161 }
162
163 /**
164 * Retrieves the reference for the given template.
165 *
166 * @param string $template
167 * @return string
168 */
169 public function getReference(string $template): string
170 {
171 $template = explode('|', $template);
172 $template = $template [0];
173 $templateString = $template;
174
175 $templateReferences = $this->config->get('template_references');
176
177 if (isset($templateReferences[$template])) {
178 $templateString = $templateReferences[$template];
179 }
180
181 $parserReferences = $this->config->get('parser_references');
182
183 foreach ($parserReferences as $reference => $fields) {
184 if (in_array($templateString, $fields)) {
185 $templateString = $reference . $this->config->get('parser_separator') . $templateString;
186
187 break;
188 }
189 }
190
191 return $templateString;
192 }
193
194 /**
195 * Parses the template with the given data.
196 *
197 * @param string $template
198 * @param array $data
199 * @return string
200 * @throws BindingResolutionException
201 */
202 public function parseTemplate(string $template, array $data): string
203 {
204 $templateParts = $this->getTemplateWrapper();
205
206
207 $start = preg_quote($templateParts['start'], '/');
208 $end = preg_quote($templateParts['end'], '/');
209
210 $pattern = '/(' . $start . '|##)+(.*?)(' . $end . '|##)/';
211 // $pattern = '/(' . $start . '|##)((?:[^' . $end[0] . '#]|(?R))*)(' . $end . '|##)/';
212
213
214 return preg_replace_callback($pattern, function ($matches) use ($data) {
215 if (empty($matches[2])) {
216 return apply_filters($this->hookPrefix . 'smartcode_fallback', $matches[0], $data);
217 }
218 $code = trim($matches[2]);
219 $transformed = $this->parseCode($code, $data);
220
221 if($transformed === $code) {
222 return $matches[0];
223 }
224
225 return $transformed;
226
227 }, $template);
228 }
229
230 /**
231 * Configures the parser with new settings.
232 * @return SmartCodeParser
233 */
234 public static function make(): SmartCodeParser
235 {
236 return new static();
237 }
238
239 /**
240 * Retrieves the template wrapper parts.
241 *
242 * @return array
243 */
244 public function getTemplateWrapper(): array
245 {
246 preg_match('/^(.*):template:(.*)$/', $this->config->get('template_string'), $matches);
247
248 return [
249 'start' => $matches[1],
250 'end' => $matches[2],
251 ];
252 }
253
254 /**
255 * Wraps the given code with the template wrapper.
256 *
257 * @param string $code
258 * @return string
259 */
260 public function wrapSmartCode(string $code): string
261 {
262 $wrapper = $this->getTemplateWrapper();
263 return $wrapper['start'] . $code . $wrapper['end'];
264 }
265 }
266