PluginProbe
FluentSnippets – High-Performance Code Snippets, Header & Footer Code, Custom CSS & PHP Code Manager / 10.33
FluentSnippets – High-Performance Code Snippets, Header & Footer Code, Custom CSS & PHP Code Manager v10.33
10.56 1.2.1 10 10.1 10.2 10.3 10.31 10.32 10.33 10.34 10.50 10.51 10.52 10.53 10.55 9.0 9.0.1 9.4 trunk 1.0.0 1.1 1.2
easy-code-manager / app / Services / CodeRunner.php

CodeRunner.php in FluentSnippets – High-Performance Code Snippets, Header & Footer Code, Custom CSS & PHP Code Manager 10.33, at app/Services/CodeRunner.php

255 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentSnippets\App\Services;
4
5 class CodeRunner
6 {
7
8 private $storageDir = '';
9
10 public function __construct()
11 {
12 $this->storageDir = WP_CONTENT_DIR . '/fluent-snippet-storage';
13 }
14
15 public function runSnippets()
16 {
17 if (!is_file($this->storageDir . '/index.php')) {
18 return;
19 }
20
21 $config = include $this->storageDir . '/index.php';
22
23 if (empty($config) || empty($config['published']) || !is_array($config['published'])) {
24 return; // No config or published scripts exist exists
25 }
26
27 if (isset($config['meta']['force_disabled']) && $config['meta']['force_disabled'] == 'yes') {
28 return; // this forcefully disabled via URL
29 }
30
31 $errorFiles = $this->get($config, 'error_files', []);
32
33 $snippets = $config['published'];
34
35 if (!$snippets) {
36 return;
37 }
38
39 $storageDir = $this->storageDir;
40
41 $hasInvalidFiles = false;
42
43 $conditionalClass = new FluentSnippetCondition();
44
45 $filterMaps = [
46 'before_content' => [
47 'hook' => 'the_content',
48 'insert' => 'before',
49 'is_single' => true
50 ],
51 'after_content' => [
52 'hook' => 'the_content',
53 'insert' => 'after',
54 'is_single' => true
55 ],
56 ];
57
58 foreach ($snippets as $fileName => $snippet) {
59 if (isset($_REQUEST['fluent_saving_snippet_name'])) {
60 if ($_REQUEST['fluent_saving_snippet_name'] === $fileName && current_user_can('manage_options')) {
61 continue;
62 }
63 }
64
65 if ($errorFiles && isset($errorFiles[$fileName])) {
66 // There has an error. Skip this
67 continue;
68 }
69
70 $file = $storageDir . '/' . sanitize_file_name($fileName);
71 if (!is_file($file)) {
72 $hasInvalidFiles = true;
73 continue;
74 }
75
76 $type = $this->get($snippet, 'type');
77
78 switch ($type) {
79 case 'PHP':
80 $conditionSettings = $snippet['condition'];
81 $hookName = 'init';
82 if (empty($conditionSettings) || empty($conditionSettings['status']) || $conditionSettings['status'] != 'yes' || empty($conditionSettings['items'])) {
83 $hookName = 'setup_theme';
84 }
85
86 add_action($hookName, function () use ($file, $snippet, $conditionalClass) {
87 if (!$conditionalClass->evaluate($snippet['condition'])) {
88 return;
89 }
90
91 $runAt = $this->get($snippet, 'run_at', 'all');
92 if ($runAt == 'backend') {
93 if (is_admin()) {
94 require_once $file;
95 }
96 return;
97 }
98
99 require_once $file;
100 }, $this->get($snippet, 'priority', 10));
101
102 break;
103 case 'js':
104 $runAt = $this->get($snippet, 'run_at', 'wp_footer');
105 if (in_array($runAt, ['wp_head', 'wp_footer', 'admin_head', 'admin_footer'])) {
106 add_action($runAt, function () use ($file, $snippet, $conditionalClass) {
107 if (!$conditionalClass->evaluate($snippet['condition'])) {
108 return;
109 }
110
111 $code = $this->parseBlock(file_get_contents($file), true);
112 ?>
113 <script><?php echo $this->escCssJs($code); // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?></script>
114 <?php
115 }, $this->get($snippet, 'priority', 10));
116 }
117 break;
118 case 'css':
119 $runAt = $this->get($snippet, 'run_at', 'wp_head');
120 if (($runAt == 'everywehere' && is_admin()) || $runAt == 'admin_head') {
121 $runAt = 'admin_head';
122 } else {
123 $runAt = 'wp_head';
124 }
125
126 add_action($runAt, function () use ($file, $snippet, $conditionalClass) {
127 if (!$conditionalClass->evaluate($snippet['condition'])) {
128 return;
129 }
130 $code = $this->parseBlock(file_get_contents($file), true);
131 ?>
132 <style><?php echo $this->escCssJs($code); // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?></style>
133 <?php
134 }, $this->get($snippet, 'priority', 10));
135 break;
136 case 'php_content':
137 $runAt = $snippet['run_at'];
138 if (in_array($runAt, ['wp_footer', 'wp_head', 'wp_body_open'])) {
139 add_action($runAt, function () use ($file, $snippet, $conditionalClass) {
140 if (!$conditionalClass->evaluate($snippet['condition'])) {
141 return;
142 }
143 require_once $file;
144 }, $snippet['priority']);
145 }
146 if (isset($filterMaps[$runAt])) {
147 $filter = $filterMaps[$runAt];
148 add_filter($filter['hook'], function ($content) use ($file, $snippet, $conditionalClass, $filter) {
149 if (!empty($filter['is_single'])) {
150 if (!is_singular() || !in_the_loop() || !is_main_query()) {
151 return $content;
152 }
153 }
154
155 if (!$conditionalClass->evaluate($snippet['condition'])) {
156 return $content;
157 }
158
159 ob_start();
160 require_once $file;
161 $result = ob_get_clean();
162 if ($result) {
163 if ($filter['insert'] == 'before') {
164 return $result . $content;
165 }
166
167 return $content . $result;
168 }
169 return $content;
170 }, $this->get($snippet, 'priority', 10));
171 }
172 default:
173 break;
174 }
175 }
176
177 if ($hasInvalidFiles) {
178 do_action('fluent_snippets/rebuild_index', false, true);
179 }
180
181 do_action('fluent_snippets/after_run_snippets');
182 }
183
184
185 private function get($array, $key, $default = null)
186 {
187 if (isset($array[$key])) {
188 return $array[$key];
189 }
190
191 return $default;
192 }
193
194 private function parseBlock($fileContent, $codeOnly = false)
195 {
196 // get content from // <Internal Doc Start> to // <Internal Doc End>
197 $fileContent = explode('// <Internal Doc Start>', $fileContent);
198
199 if (count($fileContent) < 2) {
200 if ($codeOnly) {
201 return '';
202 }
203 return [null, null];
204 }
205
206 $fileContent = explode('// <Internal Doc End> ?>' . PHP_EOL, $fileContent[1]);
207 $docBlock = $fileContent[0];
208 $code = $fileContent[1];
209
210 if ($codeOnly) {
211 return $code;
212 }
213
214 $docBlock = explode('*', $docBlock);
215 // Explode by : and get the key and value
216 $docBlockArray = [
217 'name' => '',
218 'status' => '',
219 'tags' => '',
220 'description' => '',
221 'type' => '',
222 'run_at' => '',
223 'group' => ''
224 ];
225
226 foreach ($docBlock as $key => $value) {
227 $value = trim($value);
228 $arr = explode(':', $value);
229 if (count($arr) < 2) {
230 continue;
231 }
232
233 // get the first item from the array and remove it from $arr
234 $key = array_shift($arr);
235 $key = trim(str_replace('@', '', $key));
236 if (!$key) {
237 continue;
238 }
239 $docBlockArray[$key] = trim(implode(':', $arr));
240 }
241
242 return [$docBlockArray, $code];
243 }
244
245
246 private function escCssJs($code)
247 {
248 $code = preg_replace('/<script[^>]*>/', '', $code);
249 $code = preg_replace('/<\/script>/', '', $code);
250 // remove opening js tag and closing js tag maybe <script type="text/javascript"> too
251 $code = preg_replace('/<style[^>]*>/', '', $code);
252 return preg_replace('/<\/style>/', '', $code);
253 }
254 }
255