Skip to content

Commit a26b733

Browse files
committed
Initial commit
Changes to be committed: new file: Ajax.php new file: Assets.php new file: Assets/dist/FileManager.js new file: Assets/dist/ListFile.js new file: Assets/dist/ListFile.js.LICENSE.txt new file: Assets/dist/ModalAssets.js new file: Assets/dist/index.js new file: Assets/src/FileManager.ts new file: Assets/src/ListFile.ts new file: Assets/src/ModalAssets.ts new file: Assets/src/index.js new file: Controller/Admin.php new file: Controller/Guest.php new file: Service.php new file: icon.svg new file: info.yml new file: map.json new file: mimeType.json new file: readme.md new file: roles.json new file: uploads/1715207961370 new file: uploads/1715213880497 new file: uploads/1715216076429 new file: uploads/1715272150492 new file: uploads/1715330435256 new file: uploads/1715360286695 new file: uploads/1715366410562 new file: uploads/1715390120998 new file: uploads/1715396504667 new file: uploads/1715445356358 new file: uploads/1715487347956 new file: uploads/1722215662391 new file: uploads/1722487889602 new file: uploads/silen
0 parents  commit a26b733

34 files changed

+4071
-0
lines changed

Ajax.php

Lines changed: 655 additions & 0 deletions
Large diffs are not rendered by default.

Assets.php

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
<?php
2+
3+
namespace MerapiPanel\Module\FileManager;
4+
5+
use MerapiPanel\Box;
6+
use MerapiPanel\Box\FileFragment;
7+
use MerapiPanel\Box\FileLoader;
8+
use MerapiPanel\Box\Module\__Fragment;
9+
use MerapiPanel\Box\Module\Entity\Module;
10+
use MerapiPanel\Utility\Http\Request;
11+
use MerapiPanel\Utility\Http\Response;
12+
use Symfony\Component\Filesystem\Path;
13+
14+
15+
class ModuleFileAssetsLoader extends FileLoader
16+
{
17+
18+
public function getFile(string $name): Box\FileFragment|null
19+
{
20+
21+
preg_match("/\@(\w+)/i", $name, $matches); // get module name
22+
if (isset($matches[1])) { // assets with module namespace
23+
$moduleName = ucfirst($matches[1]); // add module namespace
24+
$module = Box::module($moduleName); // get module
25+
$modulePath = $module->path; // module path
26+
// $modulePath = $_ENV['__MP_APP__'] . "/Module/" . $moduleName; // module path
27+
$path = ltrim(str_replace("@" . $matches[1], "", $name), "\\/"); // remove module namespace from path
28+
29+
if (strpos($path, "assets") !== 0 && file_exists($modulePath . "/assets/" . $path)) {
30+
$path = "assets/" . $path;
31+
} else if (strpos($path, "Assets") !== 0 && file_exists($modulePath . "/Assets/" . $path)) {
32+
$path = "Assets/" . $path;
33+
}
34+
35+
return new FileFragment(Path::join($modulePath, $path));
36+
}
37+
38+
return null;
39+
40+
}
41+
}
42+
43+
class BuildinFilesLoader extends FileLoader
44+
{
45+
46+
public function getFile(string $name): Box\FileFragment|null
47+
{
48+
49+
$name = ltrim($name, "\\/");
50+
51+
if (file_exists(Path::join($this->directory, $name)))
52+
// file in directory directly
53+
{
54+
$path = Path::join($this->directory, $name);
55+
} else if (strpos($name, "assets") !== 0 && file_exists(Path::join($this->directory, "assets", $name)))
56+
// case sensitive in linux
57+
{
58+
$path = Path::join($this->directory, "assets", $name);
59+
} else if (strpos($name, "Assets") !== 0 && file_exists(Path::join($this->directory, "Assets", $name)))
60+
// case sensitive in linux
61+
{
62+
$path = Path::join($this->directory, "Assets", $name);
63+
}
64+
65+
if (isset($path) && file_exists($path)) {
66+
return new FileFragment($path);
67+
}
68+
return null;
69+
}
70+
}
71+
72+
73+
74+
enum AssetsType: string
75+
{
76+
case BUILDIN = "buildin";
77+
case MODULE = "module";
78+
}
79+
80+
81+
82+
class Assets extends __Fragment
83+
{
84+
85+
public string $routeLink = "/public/assets/{data}";
86+
protected Module $module;
87+
88+
protected $loaders = [
89+
AssetsType::BUILDIN->value => [],
90+
AssetsType::MODULE->value => []
91+
];
92+
93+
94+
function onCreate(Module $module)
95+
{
96+
$this->module = $module;
97+
$this->loaders = [
98+
AssetsType::BUILDIN->value => [
99+
new BuildinFilesLoader(Path::join($_ENV['__MP_APP__'], "Buildin"))
100+
],
101+
AssetsType::MODULE->value => [
102+
new ModuleFileAssetsLoader(Path::join($_ENV['__MP_APP__'], "Module"))
103+
]
104+
];
105+
}
106+
107+
108+
109+
public function addLoader(AssetsType|string $type, FileLoader $loader)
110+
{
111+
if (!in_array($type, array_keys($this->loaders))) {
112+
throw new \Exception("Invalid type: " . $type);
113+
}
114+
$this->loaders[$type instanceof AssetsType ? $type->value : $type][] = $loader;
115+
}
116+
117+
118+
119+
120+
/**
121+
* Generates a URL for the given absolute file path, with caching for performance.
122+
*
123+
* @param string $absoluteFilePath The absolute file path for which to generate the URL
124+
* @return string The generated URL
125+
*/
126+
public function url($absoluteFilePath, $encrypt = false)
127+
{
128+
// Remove query string from the absolute file path
129+
$absoluteFilePath = preg_replace("/\?.*/", "", $absoluteFilePath);
130+
$final = str_replace("{data}", $absoluteFilePath, $this->routeLink);
131+
// Return the generated URL
132+
return $final;
133+
}
134+
135+
136+
137+
138+
public function getAssset(Request $req)
139+
{
140+
141+
$realPath = $this->getRealPath($req->data);
142+
143+
if (!$realPath || !is_file($realPath)) {
144+
return [
145+
"code" => 404,
146+
"message" => "Assets not found"
147+
];
148+
}
149+
150+
return $this->sendResponse($req, $realPath);
151+
}
152+
153+
154+
155+
156+
157+
158+
private function loadAssetComponent($req, $source, $file)
159+
{
160+
161+
$refRealPath = $this->getRealPath($source);
162+
163+
if (!file_exists($refRealPath)) {
164+
return [
165+
"code" => 404,
166+
"message" => "Referer assets not found",
167+
];
168+
}
169+
170+
$dirname = dirname($refRealPath);
171+
$fullPath = rtrim($dirname, "\/") . "/" . ltrim($file, "\/");
172+
if (!file_exists($fullPath)) {
173+
$fullPath = rtrim($dirname, "\/") . "/" . pathinfo(ltrim($file, "\/"), PATHINFO_BASENAME);
174+
}
175+
if (!file_exists($fullPath)) {
176+
return [
177+
"code" => 404,
178+
"message" => "Assets not found ",
179+
];
180+
}
181+
182+
return $this->sendResponse($req, $fullPath);
183+
}
184+
185+
186+
187+
188+
189+
private function sendResponse($req, $file): Response
190+
{
191+
192+
$response = new Response();
193+
194+
if ($_ENV['__MP_CACHE__'] === true) {
195+
// Determine the last modified time of the file for caching
196+
$lastModifiedTime = filemtime($file);
197+
$etag = md5($lastModifiedTime . $file);
198+
199+
$response->setStatusCode(200);
200+
$response->setHeader("Status-Code", 200);
201+
$response->setHeader("Cache-Control", "public, max-age=86400");
202+
$response->setHeader("Last-Modified", gmdate("D, d M Y H:i:s", $lastModifiedTime) . " GMT");
203+
$response->setHeader("Etag", $etag);
204+
205+
// Check if the page has been modified since the browser's cache
206+
if ($req->http("if-modified-since") && $req->http("if-modified-since") == gmdate("D, d M Y H:i:s", $lastModifiedTime)) {
207+
// Return 304 Not Modified without any content if the ETag matches
208+
$response->setStatusCode(304);
209+
return $response;
210+
}
211+
}
212+
213+
$output = file_get_contents($file);
214+
$mimeTypes = json_decode(file_get_contents(__DIR__ . "/mimeType.json"), true);
215+
216+
// Set the appropriate Content-Type header
217+
$contentType = $mimeTypes[strtolower(pathinfo($file, PATHINFO_EXTENSION))] ?? 'application/octet-stream'; // Default to binary if MIME type is application/octet-stream
218+
$response->setHeader("Content-Type", $contentType);
219+
$response->setContent($output);
220+
221+
return $response;
222+
}
223+
224+
225+
226+
227+
228+
229+
230+
private function getRealPath($path): bool|FileFragment|null
231+
{
232+
233+
if (!$path) {
234+
return false;
235+
}
236+
237+
$file_result = null;
238+
preg_match("/\@(\w+)/i", $path, $matches); // get module name
239+
240+
if (isset($matches[1])) { // assets with module namespace
241+
/**
242+
* @var ModuleFileAssetsLoader $loader
243+
*/
244+
foreach ($this->loaders[AssetsType::MODULE->value] as $loader) {
245+
if ($file_result = $loader->getFile($path)) {
246+
break;
247+
}
248+
}
249+
} else {
250+
/**
251+
* @var BuildinFilesLoader $loader
252+
*/
253+
foreach ($this->loaders[AssetsType::BUILDIN->value] as $loader) {
254+
if ($file_result = $loader->getFile($path)) {
255+
break;
256+
}
257+
}
258+
}
259+
260+
261+
return $file_result;
262+
}
263+
264+
}

Assets/dist/FileManager.js

Lines changed: 163 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/dist/ListFile.js

Lines changed: 195 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*!
2+
* jQuery JavaScript Library v3.7.1
3+
* https://jquery.com/
4+
*
5+
* Copyright OpenJS Foundation and other contributors
6+
* Released under the MIT license
7+
* https://jquery.org/license
8+
*
9+
* Date: 2023-08-28T13:37Z
10+
*/

Assets/dist/ModalAssets.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3+
* This devtool is neither made for production nor for readable output files.
4+
* It uses "eval()" calls to create a separate source file in the browser devtools.
5+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6+
* or disable the default devtool with "devtool: false".
7+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8+
*/
9+
/******/ (() => { // webpackBootstrap
10+
/******/ "use strict";
11+
/******/ var __webpack_modules__ = ({
12+
13+
/***/ "./include/module/FileManager/assets/src/ModalAssets.ts":
14+
/*!**************************************************************!*\
15+
!*** ./include/module/FileManager/assets/src/ModalAssets.ts ***!
16+
\**************************************************************/
17+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18+
19+
eval("__webpack_require__.r(__webpack_exports__);\nvar __ = window.__;\nvar FileManager = {\n endpoints: {\n upload: null,\n fetch: null,\n \"delete\": null\n }\n};\n__.FileManager = new Proxy(FileManager, {\n get: function get(target, name) {\n if (target[name]) {\n return target[name];\n }\n return null;\n },\n set: function set(target, name, value) {\n throw new Error(\"Error: Can't change FileManager object\");\n }\n});\n\n\n//# sourceURL=webpack://merapipanel/./include/module/FileManager/assets/src/ModalAssets.ts?");
20+
21+
/***/ })
22+
23+
/******/ });
24+
/************************************************************************/
25+
/******/ // The require scope
26+
/******/ var __webpack_require__ = {};
27+
/******/
28+
/************************************************************************/
29+
/******/ /* webpack/runtime/make namespace object */
30+
/******/ (() => {
31+
/******/ // define __esModule on exports
32+
/******/ __webpack_require__.r = (exports) => {
33+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
34+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
35+
/******/ }
36+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
37+
/******/ };
38+
/******/ })();
39+
/******/
40+
/************************************************************************/
41+
/******/
42+
/******/ // startup
43+
/******/ // Load entry module and return exports
44+
/******/ // This entry module can't be inlined because the eval devtool is used.
45+
/******/ var __webpack_exports__ = {};
46+
/******/ __webpack_modules__["./include/module/FileManager/assets/src/ModalAssets.ts"](0, __webpack_exports__, __webpack_require__);
47+
/******/
48+
/******/ })()
49+
;

Assets/dist/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3+
* This devtool is neither made for production nor for readable output files.
4+
* It uses "eval()" calls to create a separate source file in the browser devtools.
5+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6+
* or disable the default devtool with "devtool: false".
7+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8+
*/
9+
/******/ (() => { // webpackBootstrap
10+
/******/ var __webpack_modules__ = ({
11+
12+
/***/ "./include/module/FileManager/assets/src/index.js":
13+
/*!********************************************************!*\
14+
!*** ./include/module/FileManager/assets/src/index.js ***!
15+
\********************************************************/
16+
/***/ (() => {
17+
18+
eval("\n\n//# sourceURL=webpack://merapipanel/./include/module/FileManager/assets/src/index.js?");
19+
20+
/***/ })
21+
22+
/******/ });
23+
/************************************************************************/
24+
/******/
25+
/******/ // startup
26+
/******/ // Load entry module and return exports
27+
/******/ // This entry module can't be inlined because the eval devtool is used.
28+
/******/ var __webpack_exports__ = {};
29+
/******/ __webpack_modules__["./include/module/FileManager/assets/src/index.js"]();
30+
/******/
31+
/******/ })()
32+
;

0 commit comments

Comments
 (0)