OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
<?php
/**
* newClient Class - Add a new client
*/
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Core\Support\FromFormat;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar;
use Symfony\Component\HttpFoundation\Response;
class AddEvent extends Controller
{
private Calendar $calendarService;
/**
* init - initialize private variables
*/
public function init(Calendar $calendarService): void
{
$this->calendarService = $calendarService;
}
#[RequiresPermission(CalendarPermissions::CREATE)]
public function get(array $params): Response
{
$values = [
'description' => '',
'dateFrom' => '',
'dateTo' => '',
'allDay' => '',
];
$this->tpl->assign('values', $values);
return $this->tpl->displayPartial('calendar.addEvent');
}
#[RequiresPermission(CalendarPermissions::CREATE)]
public function post(array $params): Response
{
// Time comes in as 24:00 time from html5 element. Make it user date format
$params['timeFrom'] = format(value: $params['timeFrom'], fromFormat: FromFormat::User24hTime)->userTime24toUserTime();
$params['timeTo'] = format(value: $params['timeTo'], fromFormat: FromFormat::User24hTime)->userTime24toUserTime();
$result = $this->calendarService->addEvent($params);
if (is_numeric($result) === true) {
$this->tpl->setNotification('notification.event_created_successfully', 'success');
return Frontcontroller::redirect(BASE_URL.'/calendar/editEvent/'.$result);
} else {
$this->tpl->setNotification('notification.please_enter_title', 'error');
$this->tpl->assign('values', $params);
return $this->tpl->displayPartial('calendar.addEvent');
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
/**
* CalendarSettings Controller - Displays calendar settings modal.
*
* Plugins can register additional settings sections via the filter:
* 'leantime.domain.calendar.controllers.calendarsettings.get.calendarSettings.sections'
*
* Plugins can mark calendars as plugin-managed (hides edit/delete UI) via the filter:
* 'leantime.domain.calendar.controllers.calendarsettings.get.calendarSettings.externalCalendars'
*
* Section array structure:
* - id: string (unique identifier)
* - icon: string (FontAwesome class or SVG markup)
* - iconType: string ('fontawesome'|'svg', default 'fontawesome')
* - title: string (section heading)
* - description: string (optional description text)
* - content: string (raw HTML content - plugin must sanitize)
* - actions: array (optional action buttons with url, label, class, icon, type keys)
*/
class CalendarSettings extends Controller
{
private CalendarService $calendarService;
/**
* Initialize the controller with dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Display the Calendar Settings modal.
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function get(array $params): Response
{
// Get external calendars for the current user
$externalCalendars = $this->calendarService->getMyExternalCalendars((int) session('userdata.id'));
// Plugins can augment calendar data (e.g., add 'managedByPlugin' => true to hide edit/delete)
$externalCalendars = self::dispatchFilter('calendarSettings.externalCalendars', $externalCalendars);
// Plugins can add their settings sections via this filter
$pluginSections = self::dispatchFilter('calendarSettings.sections', []);
$this->tpl->assign('externalCalendars', $externalCalendars);
$this->tpl->assign('pluginSections', $pluginSections);
return $this->tpl->displayPartial('calendar.calendarSettings');
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller as FrontcontrollerCore;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
/**
* ConnectCalendar Controller - Displays extensible modal for connecting external calendars.
*
* Plugins can register additional calendar providers via the filter:
* 'leantime.domain.calendar.controllers.connectcalendar.get.connectOptions.providers'
*
* Provider array structure:
* - id: string (unique identifier)
* - icon: string (FontAwesome class or SVG markup)
* - iconType: string ('fontawesome'|'svg', default 'fontawesome')
* - title: string (display name)
* - description: string (short description)
* - actionUrl: string (URL to connect)
* - actionLabel: string (button text)
* - actionType: string ('link'|'modal', default 'link')
*/
class ConnectCalendar extends Controller
{
private CalendarService $calendarService;
/**
* Initialize the controller with dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Display the Connect Calendar modal with available providers.
*/
#[RequiresPermission(CalendarPermissions::CREATE)]
public function get(array $params): Response
{
$providers = self::dispatchFilter('connectOptions.providers', []);
$this->tpl->assign('providers', $providers);
return $this->tpl->displayPartial('calendar.connectCalendar');
}
/**
* Handle iCal calendar import submission.
*/
#[RequiresPermission(CalendarPermissions::CREATE)]
public function post(array $params): Response
{
if (isset($params['name']) || isset($params['url'])) {
$values = [
'url' => $params['url'] ?? '',
'name' => $params['name'] ?? 'My Calendar',
'colorClass' => $params['colorClass'] ?? '#082236',
];
$this->calendarService->addExternalCalendarUrl($values);
$this->tpl->setNotification('notification.gcal_imported_successfully', 'success', 'externalcalendar_created');
}
return FrontcontrollerCore::redirect(BASE_URL.'/calendar/showMyCalendar');
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* delClient Class - Deleting clients
*/
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class DelEvent extends Controller
{
private CalendarService $calendarService;
/**
* init - initialize private variables
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* retrieves delete calendar event page data
*/
#[RequiresPermission(CalendarPermissions::DELETE)]
public function get(array $params): Response
{
return $this->tpl->displayPartial('calendar.delEvent');
}
/**
* sets, creates, and updates edit calendar event page data
*/
#[RequiresPermission(CalendarPermissions::DELETE)]
public function post(array $params): Response
{
if (isset($_GET['id']) === false) {
return Frontcontroller::redirect(BASE_URL.'/calendar/showMyCalendar/');
}
$id = (int) $_GET['id'];
$result = $this->calendarService->delEvent($id);
if (is_numeric($result) === true) {
$this->tpl->setNotification('notification.event_removed_successfully', 'success');
return Frontcontroller::redirect(BASE_URL.'/calendar/showMyCalendar/');
} else {
$this->tpl->setNotification('notification.could_not_delete_event', 'error');
return $this->tpl->displayPartial('calendar.delEvent');
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* delClient Class - Deleting clients
*/
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class DelExternalCalendar extends Controller
{
private CalendarService $calendarService;
/**
* init - initialize private variables
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* retrieves delete calendar event page data
*/
#[RequiresPermission(CalendarPermissions::DELETE)]
public function get(array $params): Response
{
return $this->tpl->displayPartial('calendar.delExternalCal');
}
/**
* sets, creates, and updates edit calendar event page data
*/
#[RequiresPermission(CalendarPermissions::DELETE)]
public function post(array $params): Response
{
if (isset($_GET['id']) === false) {
return Frontcontroller::redirect(BASE_URL.'/calendar/showMyCalendar/');
}
$id = (int) $_GET['id'];
$result = $this->calendarService->deleteGCal($id);
if ($result === true) {
$this->tpl->setNotification('notification.calendar_removed_successfully', 'success');
return Frontcontroller::redirect(BASE_URL.'/calendar/showMyCalendar/');
} else {
$this->tpl->setNotification('notification.could_not_delete_calendar', 'error');
return $this->tpl->displayPartial('calendar.delEvent');
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* editEvent Class - Add a new client
*/
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Core\Support\FromFormat;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class EditEvent extends Controller
{
private CalendarService $calendarService;
/**
* init - initialize private variables
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* retrieves edit calendar event page data
*/
#[RequiresPermission(CalendarPermissions::EDIT)]
public function get(array $params): Response
{
$values = $this->calendarService->getEvent($params['id']);
$this->tpl->assign('values', $values);
return $this->tpl->displayPartial('calendar.editEvent');
}
/**
* sets, creates, and updates edit calendar event page data
*/
#[RequiresPermission(CalendarPermissions::EDIT)]
public function post(array $params): Response
{
$params['id'] = $_GET['id'] ?? null;
// Time comes in as 24:00 time from html5 element. Make it user date format
$params['timeFrom'] = format(value: $params['timeFrom'], fromFormat: FromFormat::User24hTime)->userTime24toUserTime();
$params['timeTo'] = format(value: $params['timeTo'], fromFormat: FromFormat::User24hTime)->userTime24toUserTime();
$result = $this->calendarService->editEvent($params);
if ($result === true) {
$this->tpl->setNotification('notification.event_edited_successfully', 'success');
} else {
$this->tpl->setNotification('notification.please_enter_title', 'error');
}
return Frontcontroller::redirect(BASE_URL.'/calendar/editEvent/'.$params['id']);
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class EditExternal extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Displays the edit external calendar form.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::EDIT)]
public function get(array $params): Response
{
if (! isset($params['id'])) {
return $this->tpl->display('errors.error403', responseCode: 403);
}
$calendar = $this->calendarService->getExternalCalendar((int) $params['id'], session('userdata.id'));
$this->tpl->assign('values', $calendar);
return $this->tpl->displayPartial('calendar.editExternalCalendar');
}
/**
* Handles external calendar update.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::EDIT)]
public function post(array $params): Response
{
if (! isset($params['id'])) {
return $this->tpl->display('errors.error403', responseCode: 403);
}
$id = (int) $params['id'];
$calendar = $this->calendarService->getExternalCalendar($id, session('userdata.id'));
$values = $calendar;
if (isset($_POST['save'])) {
$values = [
'id' => $calendar['id'],
'url' => $_POST['url'],
'name' => $_POST['name'],
'colorClass' => $_POST['colorClass'],
];
$this->calendarService->editExternalCalendar($values, $id);
$this->tpl->setNotification('notification.external_calendar_edited', 'success', 'externalCalendar_edited');
}
$this->tpl->assign('values', $values);
return $this->tpl->displayPartial('calendar.editExternalCalendar');
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Leantime\Domain\Setting\Services\Setting as SettingService;
use Symfony\Component\HttpFoundation\Response;
class Export extends Controller
{
private SettingService $settingService;
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(
SettingService $settingService,
CalendarService $calendarService
): void {
$this->settingService = $settingService;
$this->calendarService = $calendarService;
}
/**
* Displays the calendar export page.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function get(array $params): Response
{
if (isset($_GET['remove'])) {
$this->settingService->deleteSetting('usersettings.'.session('userdata.id').'.icalSecret');
$this->tpl->setNotification('notifications.ical_removed_success', 'success');
}
$this->assignUrl();
return $this->tpl->displayPartial('calendar.export');
}
/**
* Handles iCal URL generation.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function post(array $params): Response
{
if (isset($_POST['generateUrl'])) {
try {
$this->calendarService->generateIcalHash();
$this->tpl->setNotification('notifications.ical_success', 'success');
} catch (\Exception $e) {
$this->tpl->setNotification('There was a problem generating the ical hash', 'error');
}
}
$this->assignUrl();
return $this->tpl->displayPartial('calendar.export');
}
/**
* Assigns the iCal URL to the template.
*/
private function assignUrl(): void
{
$icalUrl = '';
try {
$icalUrl = $this->calendarService->getICalUrl();
} catch (\Exception $e) {
$this->tpl->setNotification('Could not find ical URL', 'error');
}
$this->tpl->assign('url', $icalUrl);
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class ExternalCal extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Serves an external calendar's iCal content, with session-based caching.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function get(array $params): Response
{
$content = $this->calendarService->getCachedExternalCalendarContent(
(int) ($params['id'] ?? 0),
(int) session('userdata.id')
);
return new Response($content, 200, [
'Content-Type' => 'text/calendar; charset=utf-8',
]);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Controller\Controller;
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class Ical extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Serves the iCal feed for a given calendar hash.
*
* @param array $params Request parameters
*/
public function get(array $params): Response
{
try {
$calendar = $this->calendarService->getIcalByRequestToken(
$_GET['id'] ?? '',
$params['act'] ?? ''
);
return new Response($calendar->get(), 200, [
'Content-Type' => 'text/calendar; charset=utf-8',
'Content-Disposition' => 'attachment; filename="leantime-calendar.ics"',
]);
} catch (\Exception $e) {
return Frontcontroller::redirect(BASE_URL.'/errors/404');
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class ImportGCal extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Displays the import calendar form.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::CREATE)]
public function get(array $params): Response
{
$this->tpl->assign('values', [
'url' => '',
'name' => '',
'colorClass' => '',
]);
return $this->tpl->displayPartial('calendar.importGCal');
}
/**
* Handles external calendar URL import.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::CREATE)]
public function post(array $params): Response
{
$values = [
'url' => $_POST['url'] ?? '',
'name' => $_POST['name'] ?? 'My Calendar',
'colorClass' => $_POST['colorClass'] ?? '#082236',
];
if (isset($_POST['name']) || isset($_POST['url'])) {
$this->calendarService->addExternalCalendarUrl($values);
$this->tpl->setNotification('notification.gcal_imported_successfully', 'success', 'externalcalendar_created');
}
$this->tpl->assign('values', $values);
return $this->tpl->displayPartial('calendar.importGCal');
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class ShowAllGCals extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Displays all external calendars.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function get(array $params): Response
{
$this->tpl->assign('allCalendars', $this->calendarService->getMyExternalCalendars(session('userdata.id')));
return $this->tpl->display('calendar.showAllGCals');
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Leantime\Domain\Calendar\Controllers;
use Leantime\Core\Auth\Permissions\RequiresPermission;
use Leantime\Core\Controller\Controller;
use Leantime\Domain\Calendar\Permissions\CalendarPermissions;
use Leantime\Domain\Calendar\Services\Calendar as CalendarService;
use Symfony\Component\HttpFoundation\Response;
class ShowMyCalendar extends Controller
{
private CalendarService $calendarService;
/**
* Initializes dependencies.
*/
public function init(CalendarService $calendarService): void
{
$this->calendarService = $calendarService;
}
/**
* Displays the user's calendar view.
*
* @param array $params Request parameters
*/
#[RequiresPermission(CalendarPermissions::VIEW)]
public function get(array $params): Response
{
$this->tpl->assign('calendar', $this->calendarService->getCalendar(session('userdata.id')));
session(['lastPage' => BASE_URL.'/calendar/showMyCalendar/']);
$externalCalendars = $this->calendarService->getMyExternalCalendars(session('userdata.id'));
$externalCalendars = self::dispatch_filter('showMyCalendar.externalCalendars', $externalCalendars);
$this->tpl->assign('externalCalendars', $externalCalendars);
return $this->tpl->display('calendar.showMyCalendar');
}
}