303 lines
9.5 KiB
PHP
303 lines
9.5 KiB
PHP
<?php
|
|
|
|
namespace Leantime\Domain\Plugins\Services;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Leantime\Core\Configuration\Environment;
|
|
use Leantime\Core\Events\EventDispatcher;
|
|
use Leantime\Core\Language;
|
|
|
|
class Registration
|
|
{
|
|
// Plugin Id: folder name of the plugin
|
|
private string $pluginId;
|
|
|
|
private bool $distFolderRegistered = false;
|
|
|
|
public function __construct(string $pluginId)
|
|
{
|
|
$this->pluginId = $pluginId;
|
|
|
|
$this->registerManifestFolder();
|
|
}
|
|
|
|
public function registerMiddleware(array $middleware)
|
|
{
|
|
|
|
EventDispatcher::add_filter_listener('leantime.core.middleware.loadplugins.handle.pluginsEvents',
|
|
function (array $existing) use ($middleware) {
|
|
return array_merge($existing, $middleware);
|
|
}
|
|
);
|
|
|
|
EventDispatcher::add_filter_listener('leantime.core.http.httpkernel.*.plugins_middleware',
|
|
function (array $existing) use ($middleware) {
|
|
return array_merge($existing, $middleware);
|
|
}
|
|
);
|
|
|
|
}
|
|
|
|
public function registerLanguageFiles(array $languages = [])
|
|
{
|
|
$pluginId = $this->pluginId;
|
|
|
|
if (empty($languages)) {
|
|
$languages = $this->findLanguageFiles();
|
|
}
|
|
|
|
EventDispatcher::add_event_listener('leantime.core.middleware.loadplugins.handle.pluginsEvents', function () use ($languages) {
|
|
|
|
$language = app()->make(Language::class);
|
|
$config = app()->make(Environment::class);
|
|
$currentUserLanguage = session('usersettings.language');
|
|
|
|
// At this point in the stack localization has already determined user language and set up the core language
|
|
// array in the language of the users choice. First we register english if it is in the array and then we
|
|
// override with the user language
|
|
if (in_array('en-US', $languages)) {
|
|
$pluginLangArray = $this->loadPluginLanguage('en-US');
|
|
$language->mergeLanguageArray($pluginLangArray);
|
|
}
|
|
|
|
// Now check the user language and override if needed
|
|
if (in_array($currentUserLanguage, $languages)) {
|
|
$pluginLangArray = $this->loadPluginLanguage($currentUserLanguage);
|
|
$language->mergeLanguageArray($pluginLangArray);
|
|
}
|
|
|
|
}, 5);
|
|
|
|
}
|
|
|
|
private function findLanguageFiles(): array
|
|
{
|
|
$pluginPath = APP_ROOT.'/app/Plugins/';
|
|
$languageDir = '/Language/';
|
|
|
|
// Check both possible locations for language files
|
|
$pharPath = "phar://{$pluginPath}{$this->pluginId}/{$this->pluginId}.phar".$languageDir;
|
|
$regularPath = "{$pluginPath}{$this->pluginId}".$languageDir;
|
|
|
|
$languageFiles = [];
|
|
|
|
// Check regular directory first
|
|
if (is_dir($regularPath)) {
|
|
$files = scandir($regularPath);
|
|
foreach ($files as $file) {
|
|
if (substr($file, -4) === '.ini') {
|
|
$languageFiles[] = substr($file, 0, -4);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check phar if no files found in regular directory
|
|
if (empty($languageFiles) && file_exists($pharPath)) {
|
|
$files = scandir($pharPath);
|
|
foreach ($files as $file) {
|
|
if (substr($file, -4) === '.ini') {
|
|
$languageFiles[] = substr($file, 0, -4);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ! empty($languageFiles) ? $languageFiles : [];
|
|
|
|
}
|
|
|
|
private function loadPluginLanguage($language): array|false
|
|
{
|
|
|
|
if (Cache::store('installation')->has($this->pluginId.'.language.'.$language)) {
|
|
return Cache::store('installation')->get($this->pluginId.'.language.'.$language);
|
|
}
|
|
|
|
$pluginPath = APP_ROOT.'/app/Plugins/';
|
|
|
|
$pharPath = "phar://{$pluginPath}{$this->pluginId}/{$this->pluginId}.phar";
|
|
$regularPath = "{$pluginPath}{$this->pluginId}";
|
|
|
|
$languagePath = "/Language/{$language}.ini";
|
|
|
|
// Check phar first
|
|
if (file_exists($pharPath.$languagePath)) {
|
|
$completeLanguagePath = $pharPath.$languagePath;
|
|
} elseif (file_exists($regularPath.$languagePath)) {
|
|
$completeLanguagePath = $regularPath.$languagePath;
|
|
} else {
|
|
// Language file doesn't exist
|
|
Cache::store('installation')->set($this->pluginId.'.language.'.$language, false, new \DateInterval('P7D'));
|
|
|
|
return false;
|
|
}
|
|
|
|
$languageArray = parse_ini_file($completeLanguagePath, true);
|
|
|
|
// We're caching the results no matter what, language file is not going to magically appear.
|
|
// So even a false is valid as parse_ini_is too expensive to run every time
|
|
Cache::store('installation')->set($this->pluginId.'.language.'.$language, $languageArray, new \DateInterval('P7D'));
|
|
|
|
return $languageArray;
|
|
|
|
}
|
|
|
|
private function getPluginBasePath()
|
|
{
|
|
|
|
$pluginPath = APP_ROOT.'/app/Plugins/';
|
|
|
|
$pharPath = "phar://{$pluginPath}{$this->pluginId}/{$this->pluginId}.phar";
|
|
$regularPath = "{$pluginPath}{$this->pluginId}";
|
|
|
|
if (file_exists($pharPath)) {
|
|
return $pharPath;
|
|
}
|
|
|
|
if (file_exists($regularPath)) {
|
|
return $regularPath;
|
|
}
|
|
|
|
return '/';
|
|
|
|
}
|
|
|
|
public function addMenuItem(array $item, string $section, array $location)
|
|
{
|
|
|
|
$pluginId = $this->pluginId;
|
|
|
|
EventDispatcher::add_filter_listener('leantime.domain.menu.repositories.menu.getMenuStructure.menuStructures.'.$section,
|
|
function ($menu) use ($item, $location, $pluginId) {
|
|
|
|
// Prepare
|
|
$item['title'] = "<span class='".$item['icon']."'></span> ".__($item['title']);
|
|
$item['tooltip'] = __($item['tooltip']);
|
|
$item['type'] = 'item';
|
|
$item['module'] = $pluginId;
|
|
|
|
$primaryLocationKey = $location[0] ?? $menu[count($menu)];
|
|
|
|
if (count($location) <= 1) {
|
|
$menu[$primaryLocationKey] = $item;
|
|
}
|
|
|
|
if (count($location) == 2) {
|
|
$submenuLocationKey = $location[1] ?? $menu[$primaryLocationKey]['submenu'][count(
|
|
$menu[$primaryLocationKey]['submenu']
|
|
)];
|
|
|
|
$menu[$primaryLocationKey]['submenu'][$submenuLocationKey] = $item;
|
|
|
|
}
|
|
|
|
return $menu;
|
|
},
|
|
50
|
|
);
|
|
|
|
EventDispatcher::add_filter_listener('leantime.domain.menu.repositories.menu.getSectionMenuType.menuSections',
|
|
function ($routes) use ($section, $item) {
|
|
|
|
$route = str_replace('/', '.', $item['href']);
|
|
|
|
$array = explode('.', $route);
|
|
if ($route[0] == '.') {
|
|
array_shift($array);
|
|
}
|
|
$route = implode('.', $array);
|
|
|
|
return array_merge($routes, [$route => $section]);
|
|
},
|
|
);
|
|
|
|
}
|
|
|
|
public function addHeaderJs(array $jsFiles)
|
|
{
|
|
|
|
EventDispatcher::add_event_listener('leantime.*.afterLinkTags', function () use ($jsFiles) {
|
|
|
|
$mix = app()->make(\Leantime\Core\Support\Mix::class);
|
|
$basePath = $this->getPluginBasePath();
|
|
|
|
// Add jQuery UI for draggable and resizable functionality
|
|
$files = $mix->getManifest()[$basePath.'/dist'];
|
|
|
|
foreach ($jsFiles as $jsFile) {
|
|
if (isset($files[$jsFile])) {
|
|
echo '<script src="'.BASE_URL.$files[$jsFile].'"></script>';
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
protected function registerManifestFolder()
|
|
{
|
|
|
|
if ($this->distFolderRegistered === false) {
|
|
|
|
$distPath = '';
|
|
$basePath = $this->getPluginBasePath();
|
|
if (file_exists($basePath.'/dist')) {
|
|
$distPath = $basePath.'/dist';
|
|
}
|
|
|
|
if ($distPath !== '') {
|
|
EventDispatcher::add_filter_listener(
|
|
'leantime.core.support.mix.__construct.mix_manifest_directories',
|
|
function (array $directories) use ($distPath) {
|
|
return array_merge($directories, [$distPath]);
|
|
}
|
|
);
|
|
|
|
$this->distFolderRegistered = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public function addFooterJs(array $paths)
|
|
{
|
|
|
|
EventDispatcher::add_event_listener('leantime.*.beforeBodyClose', function () use ($paths) {
|
|
|
|
$mix = app()->make(\Leantime\Core\Support\Mix::class);
|
|
$basePath = $this->getPluginBasePath();
|
|
|
|
// Add jQuery UI for draggable and resizable functionality
|
|
$files = $mix->getManifest()[$basePath.'/dist'];
|
|
|
|
foreach ($paths as $jsFile) {
|
|
if (isset($files[$jsFile])) {
|
|
echo '<script src="'.BASE_URL.$files[$jsFile].'"></script>';
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
public function addCss(array $paths)
|
|
{
|
|
|
|
EventDispatcher::add_event_listener('leantime.*.afterLinkTags', function () use ($paths) {
|
|
|
|
$mix = app()->make(\Leantime\Core\Support\Mix::class);
|
|
$basePath = $this->getPluginBasePath();
|
|
|
|
// Add jQuery UI for draggable and resizable functionality
|
|
$files = $mix->getManifest()[$basePath.'/dist'];
|
|
|
|
foreach ($paths as $cssFile) {
|
|
if (isset($files[$cssFile])) {
|
|
echo '<link rel="stylesheet" href="'.BASE_URL.$files[$cssFile].'" />';
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
}
|