소스 검색

Extensions: Add symlinks support

https://github.com/forkbb/forkbb/issues/13
Example: https://github.com/MioVisman/test-extension/commit/642109d7c0dada7a926d699cbfd6a8fa20e16086
Visman 1 년 전
부모
커밋
b39197b70e
4개의 변경된 파일108개의 추가작업 그리고 1개의 파일을 삭제
  1. 44 1
      app/Models/Extension/Extension.php
  2. 40 0
      app/Models/Extension/Extensions.php
  3. 12 0
      app/lang/en/admin_extensions.po
  4. 12 0
      app/lang/ru/admin_extensions.po

+ 44 - 1
app/Models/Extension/Extension.php

@@ -161,7 +161,10 @@ class Extension extends Model
 
                         $path = $this->fileData['path'] . '/' . \ltrim($cur['file'], '\\/');
 
-                        if (! \is_file($path)) {
+                        if (
+                            $this->c->Files->isBadPath($path)
+                            || ! \is_file($path)
+                        ) {
                             return ['Template file \'%s\' not found', $cur['file']];
                         }
 
@@ -181,6 +184,46 @@ class Extension extends Model
             }
         }
 
+        if ($this->fileData['extra']['symlinks']) {
+            foreach ($this->fileData['extra']['symlinks'] as $cur) {
+                switch($cur['type']) {
+                    case 'public':
+                        if (
+                            empty($cur['target'])
+                            || empty($cur['link'])
+                            || $this->c->Files->isBadPath($cur['target'])
+                            || $this->c->Files->isBadPath($cur['link'])
+                        ) {
+                            return 'Bad symlink';
+                        }
+
+                        $target = $this->fileData['path'] . '/' . \trim($cur['target'], '\\/');
+
+                        if (
+                            ! \is_file($target)
+                            && ! \is_dir($target)
+                        ) {
+                            return ['Target \'%s\' not found', $cur['target']];
+                        }
+
+                        $link = $this->c->DIR_PUBLIC . '/' . \trim($cur['link'], '\\/');
+
+                        if (
+                            \is_file($link)
+                            || \is_dir($link)
+                        ) {
+                            return ['Link \'%s\' already exists', $cur['link']];
+                        }
+
+                        $this->prepareData['symlinks'][$target] = $link;
+
+                        break;
+                    default:
+                        return 'Invalid symlink type';
+                }
+            }
+        }
+
         return true;
     }
 

+ 40 - 0
app/Models/Extension/Extensions.php

@@ -150,6 +150,10 @@ class Extensions extends Manager
                 'extra'                      => 'required|array',
                 'extra.display-name'         => 'required|string',
                 'extra.requirements'         => 'array',
+                'extra.symlinks'             => 'array',
+                'extra.symlinks.*.type'      => 'required|string|in:public',
+                'extra.symlinks.*.target'    => 'required|string',
+                'extra.symlinks.*.link'      => 'required|string',
                 'extra.templates'            => 'array',
                 'extra.templates.*.type'     => 'required|string|in:pre',
                 'extra.templates.*.template' => 'required|string',
@@ -238,6 +242,7 @@ class Extensions extends Manager
             return false;
         }
 
+        $this->setSymlinks($ext);
         $this->updateIndividual();
 
         $this->c->DB->exec($query, $vars);
@@ -272,6 +277,8 @@ class Extensions extends Manager
             'fileData' => $ext->fileData,
         ]);
 
+        $this->removeSymlinks($ext);
+
         if (true !== $this->updateCommon($ext)) {
             $this->error = 'An error occurred in updateCommon';
 
@@ -340,12 +347,16 @@ class Extensions extends Manager
             'fileData' => $ext->fileData,
         ]);
 
+        $this->removeSymlinks($ext);
+
         if (true !== $this->updateCommon($ext)) {
             $this->error = 'An error occurred in updateCommon';
 
             return false;
         }
 
+        $this->setSymlinks($ext);
+
         if ($oldStatus) {
             $this->updateIndividual();
         }
@@ -379,6 +390,7 @@ class Extensions extends Manager
             'fileData' => $ext->fileData,
         ]);
 
+        $this->setSymlinks($ext);
         $this->updateIndividual();
 
         $this->c->DB->exec($query, $vars);
@@ -410,6 +422,7 @@ class Extensions extends Manager
             'fileData' => $ext->fileData,
         ]);
 
+        $this->removeSymlinks($ext);
         $this->updateIndividual();
 
         $this->c->DB->exec($query, $vars);
@@ -544,4 +557,31 @@ class Extensions extends Manager
 
         return $result;
     }
+
+    protected function setSymlinks(Extension $ext): bool
+    {
+        $data = $this->loadDataFromFile($this->commonFile);
+        $symlinks = $data[$ext->name]['symlinks'] ?? [];
+
+        foreach ($symlinks as $target => $link) {
+            \symlink($target, $link);
+        }
+
+        return true;
+    }
+
+    protected function removeSymlinks(Extension $ext): bool
+    {
+        $data = $this->loadDataFromFile($this->commonFile);
+        $symlinks = $data[$ext->name]['symlinks'] ?? [];
+
+        foreach ($symlinks as $target => $link) {
+            if (\is_link($link)) {
+                \is_file($link) ? \unlink($link) : \rmdir($link);
+            }
+        }
+
+        return true;
+
+    }
 }

+ 12 - 0
app/lang/en/admin_extensions.po

@@ -119,3 +119,15 @@ msgstr "An error occurred in updateCommon."
 
 msgid "Empty"
 msgstr "Empty"
+
+msgid "Invalid symlink type"
+msgstr "Invalid symlink type."
+
+msgid "Bad symlink"
+msgstr "Bad symlink."
+
+msgid "Target '%s' not found"
+msgstr "Target '%s' not found."
+
+msgid "Link '%s' already exists"
+msgstr "Link '%s' already exists."

+ 12 - 0
app/lang/ru/admin_extensions.po

@@ -119,3 +119,15 @@ msgstr "Возникла ошибка в updateCommon."
 
 msgid "Empty"
 msgstr "Пусто"
+
+msgid "Invalid symlink type"
+msgstr "Неверный тип символической ссылки."
+
+msgid "Bad symlink"
+msgstr "Плохая символическая ссылка."
+
+msgid "Target '%s' not found"
+msgstr "Target '%s' отсутствует."
+
+msgid "Link '%s' already exists"
+msgstr "Link '%s' уже существует."