Plugins support (#592)
This commit is contained in:
67
src/Controller/EventController.php
Normal file
67
src/Controller/EventController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the AdminLTE bundle.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Event\ThemeEvent;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class EventController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EventDispatcherInterface
|
||||
*/
|
||||
protected function getDispatcher()
|
||||
{
|
||||
return $this->eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $eventName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasListener($eventName)
|
||||
{
|
||||
return $this->getDispatcher()->hasListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param string $eventName
|
||||
* @return ThemeEvent|Response
|
||||
*/
|
||||
public function trigger(Request $request, string $event)
|
||||
{
|
||||
if (!$this->hasListener($event)) {
|
||||
return new Response();
|
||||
}
|
||||
|
||||
$themeEvent = new ThemeEvent($request, $this->getUser());
|
||||
$this->getDispatcher()->dispatch($event, $themeEvent);
|
||||
|
||||
return new Response($themeEvent->getContent());
|
||||
}
|
||||
}
|
||||
@@ -32,10 +32,10 @@ class CustomerFixtures extends Fixture
|
||||
public const MAX_BUDGET = 100000;
|
||||
public const MIN_GLOBAL_ACTIVITIES = 5;
|
||||
public const MAX_GLOBAL_ACTIVITIES = 50;
|
||||
public const MIN_PROJECTS_PER_CUSTOMER = 10;
|
||||
public const MAX_PROJECTS_PER_CUSTOMER = 50;
|
||||
public const MIN_PROJECTS_PER_CUSTOMER = 1;
|
||||
public const MAX_PROJECTS_PER_CUSTOMER = 25;
|
||||
public const MIN_ACTIVITIES_PER_PROJECT = 0;
|
||||
public const MAX_ACTIVITIES_PER_PROJECT = 15;
|
||||
public const MAX_ACTIVITIES_PER_PROJECT = 25;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
@@ -46,18 +46,18 @@ class CustomerFixtures extends Fixture
|
||||
|
||||
$amountCustomers = rand(self::MIN_CUSTOMERS, self::MAX_CUSTOMERS);
|
||||
for ($c = 1; $c <= $amountCustomers; $c++) {
|
||||
$visibleCustomer = 0 != $c % 3;
|
||||
$visibleCustomer = 0 != $c % 5;
|
||||
$customer = $this->createCustomer($faker, $visibleCustomer);
|
||||
|
||||
$projectForCustomer = rand(self::MIN_PROJECTS_PER_CUSTOMER, self::MAX_PROJECTS_PER_CUSTOMER);
|
||||
for ($p = 1; $p <= $projectForCustomer; $p++) {
|
||||
$visibleProject = 0 != $p % 3;
|
||||
$visibleProject = 0 != $p % 7;
|
||||
$project = $this->createProject($faker, $customer, $visibleProject);
|
||||
$manager->persist($project);
|
||||
|
||||
$activityForProject = rand(self::MIN_ACTIVITIES_PER_PROJECT, self::MAX_ACTIVITIES_PER_PROJECT);
|
||||
for ($a = 1; $a <= $activityForProject; $a++) {
|
||||
$visibleActivity = 0 != $a % 3;
|
||||
$visibleActivity = 0 != $a % 6;
|
||||
$activity = $this->createActivity($faker, $project, $visibleActivity);
|
||||
$manager->persist($activity);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ class AppExtension extends Extension implements PrependExtensionInterface
|
||||
$config = [];
|
||||
}
|
||||
|
||||
// safe alternatives to %kernel.project_dir%
|
||||
$container->setParameter('kimai.data_dir', $container->getParameter('kernel.project_dir') . '/var/data');
|
||||
$container->setParameter('kimai.plugin_dir', $container->getParameter('kernel.project_dir') . '/var/plugins');
|
||||
|
||||
$container->setParameter('kimai.languages', $config['languages']);
|
||||
$container->setParameter('kimai.calendar', $config['calendar']);
|
||||
$container->setParameter('kimai.dashboard', $config['dashboard']);
|
||||
|
||||
78
src/Event/ThemeEvent.php
Normal file
78
src/Event/ThemeEvent.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class ThemeEvent extends Event
|
||||
{
|
||||
public const JAVASCRIPT = 'app.theme.javascript';
|
||||
public const STYLESHEET = 'app.theme.css';
|
||||
public const HTML_HEAD = 'app.theme.html_head';
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
protected $request;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content = '';
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(Request $request, User $user)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Request
|
||||
*/
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(): string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return ThemeEvent
|
||||
*/
|
||||
public function addContent(string $content)
|
||||
{
|
||||
$this->content .= $content;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
use Symfony\Component\Routing\RouteCollectionBuilder;
|
||||
|
||||
@@ -64,6 +66,30 @@ class Kernel extends BaseKernel
|
||||
yield new $class();
|
||||
}
|
||||
}
|
||||
|
||||
$pluginsDir = $this->getProjectDir() . '/var/plugins';
|
||||
if (!file_exists($pluginsDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->ignoreUnreadableDirs()->directories()->name('*Bundle');
|
||||
/** @var SplFileInfo $bundleDir */
|
||||
foreach ($finder->in($pluginsDir) as $bundleDir) {
|
||||
$bundleName = $bundleDir->getRelativePathname();
|
||||
|
||||
$bundleFilename = $bundleDir->getRealPath() . '/' . $bundleName . '.php';
|
||||
if (!file_exists($bundleFilename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pluginClass = 'KimaiPlugin\\' . $bundleName . '\\' . $bundleName;
|
||||
if (!class_exists($pluginClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield new $pluginClass;
|
||||
}
|
||||
}
|
||||
|
||||
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
|
||||
@@ -106,6 +132,10 @@ class Kernel extends BaseKernel
|
||||
|
||||
// load application routes
|
||||
$routes->import($confDir . '/routes' . self::CONFIG_EXTS, '/', 'glob');
|
||||
|
||||
// load plugin routes
|
||||
$pluginsDir = $this->getProjectDir() . '/var/plugins';
|
||||
$routes->import($pluginsDir . '/*Bundle/Resources/config/routes'. self::CONFIG_EXTS, '/', 'glob');
|
||||
}
|
||||
|
||||
protected function configureFosUserRoutes(RouteCollectionBuilder $routes)
|
||||
|
||||
Reference in New Issue
Block a user