upgraded to symfony 4 #74 (#81)

This commit is contained in:
Kevin Papst
2018-01-12 20:39:07 +01:00
committed by GitHub
parent c011b83b73
commit a87355695e
232 changed files with 5260 additions and 4231 deletions

View File

@@ -1,7 +0,0 @@
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>

View File

@@ -1,35 +0,0 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle;
use AppBundle\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Kimai main application bundle.
*
* @see http://symfony.com/doc/current/cookbook/bundles/best_practices.html
* @see http://symfony.com/doc/current/best_practices/business-logic.html
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -1000);
}
}

View File

@@ -1,46 +0,0 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Repository\Query;
/**
* Can be used for advanced queries with the: UserRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
interface VisibilityInterface
{
const SHOW_VISIBLE = 1;
const SHOW_HIDDEN = 0;
const SHOW_BOTH = 2;
/**
* @return $this
*/
public function getVisibility();
/**
* @param int $visibility
* @return $this
*/
public function setVisibility($visibility);
/**
* @return bool
*/
public function isExclusiveVisibility();
/**
* @param bool $exclusiveVisibility
* @return $this
*/
public function setExclusiveVisibility($exclusiveVisibility);
}

View File

@@ -1,56 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Utils;
/**
* This class is a light interface between an external Markdown parser library
* and the application. It's generally recommended to create these light interfaces
* to decouple your application from the implementation details of the third-party library.
*
* @author Ryan Weaver <weaverryan@gmail.com>
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
*/
class Markdown
{
/**
* @var \Parsedown
*/
private $parser;
/**
* @var \HTMLPurifier
*/
private $purifier;
public function __construct()
{
$this->parser = new \Parsedown();
$purifierConfig = \HTMLPurifier_Config::create([
'Cache.DefinitionImpl' => null, // Disable caching
]);
$this->purifier = new \HTMLPurifier($purifierConfig);
}
/**
* @param string $text
*
* @return string
*/
public function toHtml($text)
{
$html = $this->parser->text($text);
$safeHtml = $this->purifier->purify($html);
return $safeHtml;
}
}

View File

@@ -1,52 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Utils;
/**
* This class is used to convert PHP date format to moment.js format
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class MomentFormatConverter
{
/**
* This defines the mapping between PHP ICU date format (key) and moment.js date format (value)
* For ICU formats see http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax
* For Moment formats see http://momentjs.com/docs/#/displaying/format/
*
* @var array
*/
private static $formatConvertRules = [
// year
'yyyy' => 'YYYY', 'yy' => 'YY', 'y' => 'YYYY',
// day
'dd' => 'DD', 'd' => 'D',
// day of week
'EE' => 'ddd', 'EEEEEE' => 'dd',
// timezone
'ZZZZZ' => 'Z', 'ZZZ' => 'ZZ',
// letter 'T'
'\'T\'' => 'T',
];
/**
* Returns associated moment.js format.
*
* @param string $format PHP Date format
*
* @return string
*/
public function convert($format)
{
return strtr($format, self::$formatConvertRules);
}
}

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use AppBundle\Entity\User;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Console\Command\Command;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
@@ -71,29 +71,29 @@ class InstallCommand extends Command
$command = $this->getApplication()->find('doctrine:schema:create');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database schema: ' . $ex->getMessage());
$io->error('Failed to create database schema ('.$ex->getCode().'): ' . $ex->getMessage());
return 2;
}
try {
$command = $this->getApplication()->find('avanzu:admin:initialize');
$command->run(new ArrayInput($arguments), $output);
$command = $this->getApplication()->find('avanzu:admin:fetch-vendor');
$command->run([], $output);
} catch (\Exception $ex) {
$io->error('Failed to initialize avanzu theme: ' . $ex->getMessage());
$io->error('Failed to fetch vendors for avanzu-admin-theme: ' . $ex->getMessage());
return 3;
}
try {
$command = $this->getApplication()->find('avanzu:admin:initialize');
$command->run(new ArrayInput(array_merge(['--web-dir' => 'public'], $arguments)), $output);
} catch (\Exception $ex) {
$io->error('Failed to initialize avanzu-admin-theme: ' . $ex->getMessage());
return 4;
}
try {
$command = $this->getApplication()->find('assets:install');
$command->run(new ArrayInput($arguments), $output);
} catch (\Exception $ex) {
$io->error('Failed to install assets: ' . $ex->getMessage());
return 4;
}
try {
$command = $this->getApplication()->find('avanzu:admin:fetch-vendor');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to fetch vendors for avanzu theme: ' . $ex->getMessage());
return 5;
}
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
@@ -24,7 +24,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class DevResetCommand extends Command
class ResetCommand extends Command
{
/**
@@ -33,7 +33,7 @@ class DevResetCommand extends Command
protected function configure()
{
$this
->setName('kimai:dev:reset')
->setName('kimai:reset-dev')
->setDescription('Resets the dev environment')
->setHelp(<<<EOT
This command will drop and re-create the database and its schemas, load development fixtures and clear the cache.
@@ -53,39 +53,32 @@ EOT
{
$io = new SymfonyStyle($input, $output);
if ($input->isInteractive()) {
if (!$this->askConfirmation(
$input,
$output,
'<question>Careful, database will be purged. Do you want to continue y/N ?</question>',
false
)) {
return;
if ($this->askConfirmation($input, $output, 'Do you want to create the database y/N ?')) {
try {
$command = $this->getApplication()->find('doctrine:database:create');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database: ' . $ex->getMessage());
return 1;
}
}
try {
$command = $this->getApplication()->find('doctrine:database:create');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database: ' . $ex->getMessage());
return 1;
}
if ($this->askConfirmation($input, $output, 'Do you want to drop and re-create the schema y/N ?')) {
try {
$command = $this->getApplication()->find('doctrine:schema:drop');
$command->run(new ArrayInput(['--force' => true]), $output);
} catch (\Exception $ex) {
$io->error('Failed to drop database schema: ' . $ex->getMessage());
return 2;
}
try {
$command = $this->getApplication()->find('doctrine:schema:drop');
$command->run(new ArrayInput(['--force' => true]), $output);
} catch (\Exception $ex) {
$io->error('Failed to drop database schema: ' . $ex->getMessage());
return 2;
}
try {
$command = $this->getApplication()->find('doctrine:schema:create');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database schema: ' . $ex->getMessage());
return 3;
try {
$command = $this->getApplication()->find('doctrine:schema:create');
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database schema: ' . $ex->getMessage());
return 3;
}
}
try {
@@ -98,16 +91,14 @@ EOT
return 4;
}
if ($input->getOption('no-cache')) {
return 0;
}
$command = $this->getApplication()->find('cache:clear');
try {
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to clear cache: ' . $ex->getMessage());
return 5;
if (!$input->getOption('no-cache')) {
$command = $this->getApplication()->find('cache:clear');
try {
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to clear cache: ' . $ex->getMessage());
return 5;
}
}
return 0;
@@ -121,10 +112,14 @@ EOT
* @param bool $default
* @return bool
*/
private function askConfirmation(InputInterface $input, OutputInterface $output, $question, $default)
private function askConfirmation(InputInterface $input, OutputInterface $output, $question, $default = false)
{
if (!$input->isInteractive()) {
return true;
}
$questionHelper = $this->getHelperSet()->get('question');
$question = new ConfirmationQuestion($question, $default);
$question = new ConfirmationQuestion('<question>' . $question . '</question>', $default);
return $questionHelper->ask($input, $output, $question);
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -30,11 +30,11 @@ class RunCodeSnifferCommand extends Command
/**
* RunCodeSnifferCommand constructor.
* @param $rootDir
* @param $projectDirectory
*/
public function __construct($rootDir)
public function __construct($projectDirectory)
{
$this->rootDir = realpath($rootDir . '/../');
$this->rootDir = realpath($projectDirectory);
parent::__construct();
}
@@ -44,7 +44,7 @@ class RunCodeSnifferCommand extends Command
protected function configure()
{
$this
->setName('kimai:dev:phpcs')
->setName('kimai:phpcs')
->setDescription('Run PHP_CodeSniffer to check for the projects coding style')
;
}
@@ -58,7 +58,7 @@ class RunCodeSnifferCommand extends Command
$this->executeCodeSniffer($io, '/src');
$this->executeCodeSniffer($io, '/tests');
$this->executeCodeSniffer($io, '/app/Resources/views');
$this->executeCodeSniffer($io, '/templates');
}
/**

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -29,7 +29,7 @@ class RunIntegrationTestsCommand extends RunUnitTestsCommand
protected function configure()
{
$this
->setName('kimai:dev:test-integration')
->setName('kimai:test-integration')
->setDescription('Run all integration tests')
->setHelp('This command will execute all integration tests with the annotation "@group integration".')
;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Command;
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -31,11 +31,11 @@ class RunUnitTestsCommand extends Command
/**
* RunCodeSnifferCommand constructor.
* @param $rootDir
* @param string $projectDirectory
*/
public function __construct($rootDir)
public function __construct($projectDirectory)
{
$this->rootDir = realpath($rootDir . '/../');
$this->rootDir = realpath($projectDirectory);
parent::__construct();
}
@@ -45,7 +45,7 @@ class RunUnitTestsCommand extends Command
protected function configure()
{
$this
->setName('kimai:dev:test-unit')
->setName('kimai:test-unit')
->setDescription('Run all unit tests')
->setHelp('This command will execute all unit tests. Skips all tests with "@group integration" annotation.')
;
@@ -58,8 +58,7 @@ class RunUnitTestsCommand extends Command
{
$io = new SymfonyStyle($input, $output);
$this->executeTests($io, '/tests/AppBundle');
$this->executeTests($io, '/tests/TimesheetBundle');
$this->executeTests($io, '/tests');
}
/**

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Controller;
namespace App\Controller;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller;
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Repository\ActivityRepository;
use App\Entity\Activity;
use App\Repository\ActivityRepository;
/**
* Controller used to manage activity contents in the public part of the site.
@@ -48,7 +48,7 @@ class ActivityController extends Controller
$activeEntries = $this->getRepository()->getRecentActivities($user, new \DateTime('-30 days'));
return $this->render(
'TimesheetBundle:Navbar:recent-activities.html.twig',
'navbar/recent-activities.html.twig',
['activities' => $activeEntries]
);
}

View File

@@ -9,21 +9,21 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller\Admin;
namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController;
use App\Controller\AbstractController;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Entity\Activity;
use App\Entity\Activity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Form\ActivityEditForm;
use TimesheetBundle\Form\Toolbar\ActivityToolbarForm;
use TimesheetBundle\Repository\Query\ActivityQuery;
use App\Entity\Customer;
use App\Entity\Project;
use App\Form\ActivityEditForm;
use App\Form\Toolbar\ActivityToolbarForm;
use App\Repository\Query\ActivityQuery;
/**
* Controller used to manage activities in the admin part of the site.
@@ -37,7 +37,7 @@ class ActivityController extends AbstractController
{
/**
* @return \TimesheetBundle\Repository\ActivityRepository
* @return \App\Repository\ActivityRepository
*/
protected function getRepository()
{
@@ -99,7 +99,7 @@ class ActivityController extends AbstractController
/* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:admin:activity.html.twig', [
return $this->render('admin/activity.html.twig', [
'entries' => $entries,
'query' => $query,
'toolbarForm' => $this->getToolbarForm($query)->createView(),
@@ -158,7 +158,7 @@ class ActivityController extends AbstractController
}
return $this->render(
'TimesheetBundle:admin:activity_delete.html.twig',
'admin/activity_delete.html.twig',
[
'activity' => $activity,
'stats' => $stats,
@@ -189,7 +189,7 @@ class ActivityController extends AbstractController
}
return $this->render(
'TimesheetBundle:admin:activity_edit.html.twig',
'admin/activity_edit.html.twig',
[
'activity' => $activity,
'form' => $editForm->createView()

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller\Admin;
namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController;
use App\Controller\AbstractController;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Entity\Customer;
use App\Entity\Customer;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use TimesheetBundle\Form\CustomerEditForm;
use TimesheetBundle\Form\Toolbar\CustomerToolbarForm;
use TimesheetBundle\Repository\Query\CustomerQuery;
use App\Form\CustomerEditForm;
use App\Form\Toolbar\CustomerToolbarForm;
use App\Repository\Query\CustomerQuery;
/**
* Controller used to manage activities in the admin part of the site.
@@ -35,7 +35,7 @@ class CustomerController extends AbstractController
{
/**
* @return \TimesheetBundle\Repository\CustomerRepository
* @return \App\Repository\CustomerRepository
*/
protected function getRepository()
{
@@ -76,7 +76,7 @@ class CustomerController extends AbstractController
/* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:admin:customer.html.twig', [
return $this->render('admin/customer.html.twig', [
'entries' => $entries,
'query' => $query,
'toolbarForm' => $this->getToolbarForm($query)->createView(),
@@ -123,7 +123,7 @@ class CustomerController extends AbstractController
return $this->redirectToRoute('admin_customer', ['id' => $customer->getId()]);
}
return $this->render('TimesheetBundle:admin:customer_edit.html.twig', [
return $this->render('admin/customer_edit.html.twig', [
'customer' => $customer,
'form' => $editForm->createView()
]);
@@ -161,7 +161,7 @@ class CustomerController extends AbstractController
return $this->redirectToRoute('admin_customer', ['id' => $customer->getId()]);
}
return $this->render('TimesheetBundle:admin:customer_delete.html.twig', [
return $this->render('admin/customer_delete.html.twig', [
'customer' => $customer,
'stats' => $stats,
'form' => $deleteForm->createView(),

View File

@@ -9,20 +9,20 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller\Admin;
namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController;
use App\Controller\AbstractController;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use App\Entity\Customer;
use App\Entity\Project;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use TimesheetBundle\Form\ProjectEditForm;
use TimesheetBundle\Form\Toolbar\ProjectToolbarForm;
use TimesheetBundle\Repository\Query\ProjectQuery;
use App\Form\ProjectEditForm;
use App\Form\Toolbar\ProjectToolbarForm;
use App\Repository\Query\ProjectQuery;
/**
* Controller used to manage projects in the admin part of the site.
@@ -36,7 +36,7 @@ class ProjectController extends AbstractController
{
/**
* @return \TimesheetBundle\Repository\ProjectRepository
* @return \App\Repository\ProjectRepository
*/
protected function getRepository()
{
@@ -87,7 +87,7 @@ class ProjectController extends AbstractController
/* @var $entries Pagerfanta */
$entries = $this->getDoctrine()->getRepository(Project::class)->findByQuery($query);
return $this->render('TimesheetBundle:admin:project.html.twig', [
return $this->render('admin/project.html.twig', [
'entries' => $entries,
'query' => $query,
'toolbarForm' => $this->getToolbarForm($query)->createView(),
@@ -145,7 +145,7 @@ class ProjectController extends AbstractController
return $this->redirectToRoute('admin_project', ['id' => $project->getId()]);
}
return $this->render('TimesheetBundle:admin:project_delete.html.twig', [
return $this->render('admin/project_delete.html.twig', [
'project' => $project,
'stats' => $stats,
'form' => $deleteForm->createView(),
@@ -173,7 +173,7 @@ class ProjectController extends AbstractController
return $this->redirectToRoute('admin_project', ['id' => $project->getId()]);
}
return $this->render('TimesheetBundle:admin:project_edit.html.twig', [
return $this->render('admin/project_edit.html.twig', [
'project' => $project,
'form' => $editForm->createView()
]);

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller\Admin;
namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController;
use App\Controller\AbstractController;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Controller\TimesheetControllerTrait;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Timesheet;
use App\Controller\TimesheetControllerTrait;
use App\Entity\Customer;
use App\Entity\Timesheet;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use TimesheetBundle\Form\TimesheetAdminForm;
use App\Form\TimesheetAdminForm;
/**
* Controller used for manage timesheet entries in the admin part of the site.
@@ -55,7 +55,7 @@ class TimesheetController extends AbstractController
/* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:admin:timesheet.html.twig', [
return $this->render('admin/timesheet.html.twig', [
'entries' => $entries,
'page' => $page,
'query' => $query,
@@ -91,7 +91,7 @@ class TimesheetController extends AbstractController
*/
public function editAction(Timesheet $entry, Request $request)
{
return $this->edit($entry, $request, 'admin_timesheet_paginated', 'TimesheetBundle:admin:timesheet_edit.html.twig');
return $this->edit($entry, $request, 'admin_timesheet_paginated', 'admin/timesheet_edit.html.twig');
}
/**
@@ -105,7 +105,7 @@ class TimesheetController extends AbstractController
*/
public function createAction(Request $request)
{
return $this->create($request, 'admin_timesheet', 'TimesheetBundle:admin:timesheet_edit.html.twig');
return $this->create($request, 'admin_timesheet', 'admin/timesheet_edit.html.twig');
}
/**

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Controller\Admin;
namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController;
use AppBundle\Entity\User;
use AppBundle\Form\Toolbar\UserToolbarForm;
use AppBundle\Form\UserCreateType;
use AppBundle\Repository\Query\UserQuery;
use App\Controller\AbstractController;
use App\Entity\User;
use App\Form\Toolbar\UserToolbarForm;
use App\Form\UserCreateType;
use App\Repository\Query\UserQuery;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
@@ -54,7 +54,7 @@ class UserController extends AbstractController
->setRole($userRole)
;
return $query ;
return $query;
}
/**

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Controller;
namespace App\Controller;
use AppBundle\Entity\User;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\User;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
@@ -41,7 +41,7 @@ class DashboardController extends Controller
$userStats = $this->getDoctrine()->getRepository(User::class)->getGlobalStatistics();
// FIXME move the other widgets to the TimesheetBundle, the inheritence is wrong as AppBundle
// FIXME move the other widgets to the Kimai, the inheritence is wrong as Kimai
// shouldn't know about Timesheets
$timesheetRepo = $this->getDoctrine()->getRepository(Timesheet::class);

View File

@@ -9,18 +9,18 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Controller;
namespace App\Controller;
use AppBundle\Entity\User;
use AppBundle\Form\UserEditType;
use AppBundle\Form\UserPasswordType;
use AppBundle\Form\UserRolesType;
use App\Entity\User;
use App\Form\UserEditType;
use App\Form\UserPasswordType;
use App\Form\UserRolesType;
use Symfony\Component\Form\Form;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\Timesheet;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use TimesheetBundle\Repository\TimesheetRepository;
use App\Repository\TimesheetRepository;
use Symfony\Component\HttpFoundation\Request;
/**

View File

@@ -9,42 +9,38 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Controller;
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
/**
* Controller used to manage the application security.
* See http://symfony.com/doc/current/cookbook/security/form_login_setup.html.
*/
class SecurityController extends Controller
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="security_login")
*/
public function loginAction()
public function login(AuthenticationUtils $helper): Response
{
$helper = $this->get('security.authentication_utils');
return $this->render('security/login.html.twig', [
'last_username' => $helper->getLastUsername(),
'error' => $helper->getLastAuthenticationError(),
]);
}
/**
* This is the route the user can use to logout.
*
* The route needs to exist!
* It could be configured in the routes.yml as well, but having it here in one place seemed to be the better was.
*
* The code will never be executed. Symfony will intercept this request and handle the logout automatically.
* See logout in app/config/security.yml
* But, this will never be executed. Symfony will intercept this first
* and handle the logout automatically. See logout in config/packages/security.yaml
*
* @Route("/logout", name="security_logout")
*/
public function logoutAction()
public function logout(): void
{
throw new \Exception('This should never be reached!');
}

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller;
namespace App\Controller;
use AppBundle\Controller\AbstractController;
use App\Controller\AbstractController;
use Pagerfanta\Pagerfanta;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Timesheet;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Form\TimesheetEditForm;
use App\Form\TimesheetEditForm;
/**
* Controller used to manage timesheet contents in the public part of the site.
@@ -50,7 +50,7 @@ class TimesheetController extends AbstractController
/* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:timesheet:index.html.twig', [
return $this->render('timesheet/index.html.twig', [
'entries' => $entries,
'page' => $page,
'query' => $query,
@@ -69,7 +69,7 @@ class TimesheetController extends AbstractController
$activeEntries = $this->getRepository()->getActiveEntries($user);
return $this->render(
'TimesheetBundle:Navbar:active-entries.html.twig',
'navbar/active-entries.html.twig',
['entries' => $activeEntries]
);
}
@@ -127,7 +127,7 @@ class TimesheetController extends AbstractController
*/
public function editAction(Timesheet $entry, Request $request)
{
return $this->edit($entry, $request, 'timesheet_paginated', 'TimesheetBundle:timesheet:edit.html.twig');
return $this->edit($entry, $request, 'timesheet_paginated', 'timesheet/edit.html.twig');
}
/**
@@ -141,7 +141,7 @@ class TimesheetController extends AbstractController
*/
public function createAction(Request $request)
{
return $this->create($request, 'timesheet', 'TimesheetBundle:timesheet:edit.html.twig');
return $this->create($request, 'timesheet', 'timesheet/edit.html.twig');
}
/**

View File

@@ -9,16 +9,16 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Controller;
namespace App\Controller;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Form\Toolbar\TimesheetToolbarForm;
use TimesheetBundle\Repository\Query\TimesheetQuery;
use TimesheetBundle\Repository\TimesheetRepository;
use App\Form\Toolbar\TimesheetToolbarForm;
use App\Repository\Query\TimesheetQuery;
use App\Repository\TimesheetRepository;
/**
* Helper functions for Timesheet controller

View File

@@ -9,26 +9,32 @@
* file that was distributed with this source code.
*/
namespace AppBundle\DataFixtures\ORM;
namespace App\DataFixtures;
use AppBundle\Entity\User;
use Doctrine\Common\DataFixtures\FixtureInterface;
use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
/**
* Sample data to load in the database when running tests or for development
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class LoadFixtures implements FixtureInterface, ContainerAwareInterface
class AppFixtures extends Fixture
{
const DEFAULT_PASSWORD = 'kitten';
/** @var ContainerInterface */
private $container;
/**
* @var UserPasswordEncoderInterface
*/
private $encoder;
public function __construct(UserPasswordEncoderInterface $encoder)
{
$this->encoder = $encoder;
}
/**
* {@inheritdoc}
@@ -40,7 +46,7 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface
private function loadUsers(ObjectManager $manager)
{
$passwordEncoder = $this->container->get('security.password_encoder');
$passwordEncoder = $this->encoder;
$claraCustomer = new User();
$claraCustomer
@@ -53,6 +59,7 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface
->setPassword($passwordEncoder->encodePassword($claraCustomer, self::DEFAULT_PASSWORD))
;
$manager->persist($claraCustomer);
var_dump($passwordEncoder->encodePassword($claraCustomer, self::DEFAULT_PASSWORD));
$johnUser = new User();
$johnUser
@@ -119,14 +126,6 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface
$manager->flush();
}
/**
* {@inheritdoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
protected function getPhrases()
{
return [

View File

@@ -9,15 +9,14 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\DataFixtures\ORM;
namespace App\DataFixtures;
use AppBundle\Entity\User;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\User;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use Doctrine\Common\Persistence\ObjectManager;
use AppBundle\DataFixtures\ORM\LoadFixtures as AppBundleLoadFixtures;
/**
* Defines the sample data to load in the database when running the unit and
@@ -27,7 +26,7 @@ use AppBundle\DataFixtures\ORM\LoadFixtures as AppBundleLoadFixtures;
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class LoadFixtures extends AppBundleLoadFixtures
class TimesheetFixtures extends AppFixtures
{
const AMOUNT_TIMESHEET = 5000; // timesheet entries total
const RATE_MIN = 10; // minimum rate for one hour
@@ -191,7 +190,7 @@ class LoadFixtures extends AppBundleLoadFixtures
->setAddress($this->getRandomLocation())
->setComment($this->getRandomPhrase())
->setVisible($visible)
->setCountry('Germany') // TODO randomize country ?
->setCountry('DE') // TODO randomize country ?
->setTimezone($allTimezones[rand(1, $amountTimezone)]);
$manager->persist($entry);

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\DependencyInjection;
namespace App\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -17,11 +17,11 @@ use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\Yaml\Yaml;
/**
* Class CompilerPass, dynamically loads additional doctrine functions for the configured database engine.
* Dynamically loads additional doctrine functions for the configured database engine.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class CompilerPass implements CompilerPassInterface
class DoctrineCompilerPass implements CompilerPassInterface
{
/**

View File

@@ -0,0 +1,36 @@
<?php
namespace App\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('kimai');
// FIXME add kimai config
$rootNode
->children()
->arrayNode('timesheet')
->children()
->integerNode('round_record')->end()
->end()
->end()
->end()
;
return $treeBuilder;
}
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\DependencyInjection;
namespace App\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
@@ -20,7 +20,7 @@ use \Doctrine\Common\ClassLoader;
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class AppExtension extends Extension
class KimaiExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
@@ -30,5 +30,8 @@ class AppExtension extends Extension
$classLoader = new ClassLoader('DoctrineExtensions', $extensionsDir);
$classLoader->register();
$kimaiConfig = new Configuration();
$this->processConfiguration($kimaiConfig, $configs);
}
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Doctrine;
namespace App\Doctrine;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Entity;
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
@@ -18,7 +18,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* Activity
*
* @ORM\Table(name="activities")
* @ORM\Entity(repositoryClass="TimesheetBundle\Repository\ActivityRepository")
* @ORM\Entity(repositoryClass="App\Repository\ActivityRepository")
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
@@ -37,7 +37,7 @@ class Activity
/**
* @var Project
*
* @ORM\ManyToOne(targetEntity="TimesheetBundle\Entity\Project", inversedBy="activities")
* @ORM\ManyToOne(targetEntity="App\Entity\Project", inversedBy="activities")
* @ORM\JoinColumn(onDelete="CASCADE")
* @Assert\NotNull()
*/
@@ -69,7 +69,7 @@ class Activity
/**
* @var Timesheet[]
*
* @ORM\OneToMany(targetEntity="TimesheetBundle\Entity\Timesheet", mappedBy="activity")
* @ORM\OneToMany(targetEntity="App\Entity\Timesheet", mappedBy="activity")
*/
private $timesheets;

View File

@@ -1,6 +1,6 @@
<?php
namespace AppBundle\Entity;
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Entity;
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
@@ -18,7 +18,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* Customer
*
* @ORM\Table(name="customers")
* @ORM\Entity(repositoryClass="TimesheetBundle\Repository\CustomerRepository")
* @ORM\Entity(repositoryClass="App\Repository\CustomerRepository")
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
@@ -54,7 +54,7 @@ class Customer
/**
* @var Project[]
*
* @ORM\OneToMany(targetEntity="TimesheetBundle\Entity\Project", mappedBy="customer")
* @ORM\OneToMany(targetEntity="App\Entity\Project", mappedBy="customer")
*/
private $projects;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Entity;
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
@@ -18,7 +18,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* Project
*
* @ORM\Table(name="projects")
* @ORM\Entity(repositoryClass="TimesheetBundle\Repository\ProjectRepository")
* @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
@@ -37,7 +37,7 @@ class Project
/**
* @var Customer
*
* @ORM\ManyToOne(targetEntity="TimesheetBundle\Entity\Customer", inversedBy="projects")
* @ORM\ManyToOne(targetEntity="App\Entity\Customer", inversedBy="projects")
* @ORM\JoinColumn(onDelete="CASCADE")
* @Assert\NotNull()
*/
@@ -77,7 +77,7 @@ class Project
/**
* @var Activity[]
*
* @ORM\OneToMany(targetEntity="TimesheetBundle\Entity\Activity", mappedBy="project")
* @ORM\OneToMany(targetEntity="App\Entity\Activity", mappedBy="project")
*/
private $activities;

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Entity;
namespace App\Entity;
use AppBundle\Entity\User;
use App\Entity\User;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
@@ -25,7 +25,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* @ORM\Index(columns={"activity_id"})
* }
* )
* @ORM\Entity(repositoryClass="TimesheetBundle\Repository\TimesheetRepository")
* @ORM\Entity(repositoryClass="App\Repository\TimesheetRepository")
* @ORM\HasLifecycleCallbacks()
*
* @author Kevin Papst <kevin@kevinpapst.de>
@@ -67,7 +67,7 @@ class Timesheet
/**
* @var User
*
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* @ORM\ManyToOne(targetEntity="App\Entity\User")
* @ORM\JoinColumn(name="user", referencedColumnName="id")
* @Assert\NotNull()
*/
@@ -76,7 +76,7 @@ class Timesheet
/**
* @var Activity
*
* @ORM\ManyToOne(targetEntity="TimesheetBundle\Entity\Activity", inversedBy="timesheets")
* @ORM\ManyToOne(targetEntity="App\Entity\Activity", inversedBy="timesheets")
* @ORM\JoinColumn(onDelete="CASCADE")
* @Assert\NotNull()
*/

View File

@@ -1,8 +1,8 @@
<?php
namespace AppBundle\Entity;
namespace App\Entity;
use AppBundle\Validator\Constraints as KimaiAssert;
use App\Validator\Constraints as KimaiAssert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@@ -12,12 +12,12 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* User
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(
* name="users",
* uniqueConstraints={
* @ORM\UniqueConstraint(name="name", columns={"name"}),
* @ORM\UniqueConstraint(name="mail", columns={"mail"})
* @ORM\UniqueConstraint(columns={"name"}),
* @ORM\UniqueConstraint(columns={"mail"})
* }
* )
* @UniqueEntity("username")

View File

@@ -1,13 +1,13 @@
<?php
namespace AppBundle\Entity;
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* UserPreference
*
* @ORM\Table(name="preferences",indexes={@ORM\Index(name="option_idx", columns={"userid", "option"})}))
* @ORM\Table(name="preferences",indexes={@ORM\Index(columns={"userid", "option"})}))
* @ORM\Entity
*/
class UserPreference

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Event;
namespace App\Event;
use Avanzu\AdminThemeBundle\Model\MenuItemModel;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Event;
namespace App\Event;
/**
* The ConfigureMainMenuEvent is used for populating the main navigation.

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Event;
namespace App\Event;
use Avanzu\AdminThemeBundle\Event\SidebarMenuEvent;
use Symfony\Component\HttpFoundation\Request;

View File

@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\EventListener;
namespace App\EventListener;
use AppBundle\Event\ConfigureMainMenuEvent;
use AppBundle\Event\ConfigureAdminMenuEvent;
use App\Event\ConfigureMainMenuEvent;
use App\Event\ConfigureAdminMenuEvent;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Avanzu\AdminThemeBundle\Model\MenuItemModel;
use Avanzu\AdminThemeBundle\Event\SidebarMenuEvent;
@@ -25,7 +25,7 @@ use Avanzu\AdminThemeBundle\Event\SidebarMenuEvent;
class Menu
{
/**
* @param \AppBundle\Event\ConfigureMainMenuEvent $event
* @param \App\Event\ConfigureMainMenuEvent $event
*/
public function onMainMenuConfigure(ConfigureMainMenuEvent $event)
{
@@ -45,7 +45,7 @@ class Menu
}
/**
* @param \AppBundle\Event\ConfigureAdminMenuEvent $event
* @param \App\Event\ConfigureAdminMenuEvent $event
*/
public function onAdminMenuConfigure(ConfigureAdminMenuEvent $event)
{

View File

@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
namespace AppBundle\EventListener;
namespace App\EventListener;
use AppBundle\Event\ConfigureMainMenuEvent;
use AppBundle\Event\ConfigureAdminMenuEvent;
use App\Event\ConfigureMainMenuEvent;
use App\Event\ConfigureAdminMenuEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Avanzu\AdminThemeBundle\Model\MenuItemModel;

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\EventListener;
namespace App\EventListener;
use AppBundle\Entity\User;
use App\Entity\User;
use Avanzu\AdminThemeBundle\Event\ShowUserEvent;
use Avanzu\AdminThemeBundle\Model\UserModel;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\EventListener;
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;

View File

@@ -9,12 +9,12 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\EventListener;
namespace App\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Event\LifecycleEventArgs;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\Timesheet;
/**
* A listener to make sure all Timesheet entries will have a proper duration.

View File

@@ -9,17 +9,17 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form;
namespace App\Form;
use AppBundle\Form\Type\VisibilityType;
use App\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Form\Type\ProjectType;
use TimesheetBundle\Repository\ProjectRepository;
use App\Entity\Activity;
use App\Form\Type\ProjectType;
use App\Repository\ProjectRepository;
/**
* Defines the form used to manipulate Activities.

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form;
namespace App\Form;
use AppBundle\Form\Type\VisibilityType;
use App\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\Extension\Core\Type\CurrencyType;
@@ -24,7 +24,7 @@ use Symfony\Component\Form\Extension\Core\Type\TimezoneType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Customer;
use App\Entity\Customer;
/**
* Defines the form used to edit Customer entities.
@@ -55,7 +55,7 @@ class CustomerEditForm extends AbstractType
/*
->add('projects', EntityType::class, [
'label' => 'label.project',
'class' => 'TimesheetBundle:Project',
'class' => 'Kimai:Project',
'multiple' => true,
'expanded' => true
])

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form;
namespace App\Form;
use AppBundle\Form\Type\VisibilityType;
use App\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Form\Type\CustomerType;
use TimesheetBundle\Repository\CustomerRepository;
use App\Entity\Customer;
use App\Entity\Project;
use App\Form\Type\CustomerType;
use App\Repository\CustomerRepository;
/**
* Defines the form used to edit Projects.

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form;
namespace App\Form;
use AppBundle\Form\Type\UserType;
use App\Form\Type\UserType;
use Symfony\Component\Form\FormBuilderInterface;
/**

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form;
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
@@ -17,10 +17,10 @@ use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Timesheet;
use TimesheetBundle\Form\Type\ActivityGroupedWithCustomerNameType;
use TimesheetBundle\Repository\ActivityRepository;
use App\Entity\Customer;
use App\Entity\Timesheet;
use App\Form\Type\ActivityGroupedWithCustomerNameType;
use App\Repository\ActivityRepository;
/**
* Defines the form used to manipulate Timesheet entries.

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use Symfony\Component\Form\AbstractType;

View File

@@ -9,12 +9,12 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Form\Type\ProjectType;
use TimesheetBundle\Repository\Query\ActivityQuery;
use App\Form\Type\ProjectType;
use App\Repository\Query\ActivityQuery;
/**
* Defines the form used for filtering the activities.

View File

@@ -9,11 +9,11 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use AppBundle\Form\Toolbar\VisibilityToolbarForm;
use App\Form\Toolbar\VisibilityToolbarForm;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Repository\Query\CustomerQuery;
use App\Repository\Query\CustomerQuery;
/**
* Defines the form used for filtering the customer.

View File

@@ -9,11 +9,11 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use AppBundle\Form\Type\PageSizeType;
use App\Form\Type\PageSizeType;
use Symfony\Component\Form\FormBuilderInterface;
use TimesheetBundle\Repository\Query\CustomerQuery;
use App\Repository\Query\CustomerQuery;
/**
* Defines the base form used for all toolbars with pageSizes.

View File

@@ -9,15 +9,15 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use AppBundle\Form\Toolbar\VisibilityToolbarForm;
use App\Form\Toolbar\VisibilityToolbarForm;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Form\Type\CustomerType;
use TimesheetBundle\Repository\CustomerRepository;
use TimesheetBundle\Repository\Query\CustomerQuery;
use TimesheetBundle\Repository\Query\ProjectQuery;
use App\Form\Type\CustomerType;
use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerQuery;
use App\Repository\Query\ProjectQuery;
/**
* Defines the form used for filtering the projects.

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Form\Type\ActivityType;
use TimesheetBundle\Repository\Query\TimesheetQuery;
use App\Form\Type\ActivityType;
use App\Repository\Query\TimesheetQuery;
/**
* Defines the form used for filtering the timesheet.

View File

@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use AppBundle\Form\Type\UserRoleType;
use AppBundle\Repository\Query\UserQuery;
use App\Form\Type\UserRoleType;
use App\Repository\Query\UserQuery;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Toolbar;
namespace App\Form\Toolbar;
use AppBundle\Form\Type\VisibilityType;
use App\Form\Type\VisibilityType;
use Symfony\Component\Form\FormBuilderInterface;
/**

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Type;
namespace App\Form\Type;
use TimesheetBundle\Entity\Activity;
use App\Entity\Activity;
/**
* Custom form field type to select an activity which are grouped by their Projects, preceeded by their customer names.

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Repository\ActivityRepository;
use App\Entity\Activity;
use App\Repository\ActivityRepository;
/**
* Custom form field type to select an activity.
@@ -48,7 +48,7 @@ class ActivityType extends AbstractType
{
$resolver->setDefaults([
'label' => 'label.activity',
'class' => 'TimesheetBundle:Activity',
'class' => 'Kimai:Activity',
'choice_label' => [$this, 'choiceLabel'],
'group_by' => [$this, 'groupBy'],
'query_builder' => function (ActivityRepository $repo) {

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Repository\CustomerRepository;
use TimesheetBundle\Repository\Query\CustomerQuery;
use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerQuery;
/**
* Custom form field type to select a customer.
@@ -32,7 +32,7 @@ class CustomerType extends AbstractType
{
$resolver->setDefaults([
'label' => 'label.customer',
'class' => 'TimesheetBundle:Customer',
'class' => 'Kimai:Customer',
'choice_label' => 'name',
'query_builder' => function (CustomerRepository $repo) {
return $repo->builderForEntityType(null);

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use AppBundle\Utils\MomentFormatConverter;
use App\Utils\MomentFormatConverter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormInterface;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

View File

@@ -9,14 +9,14 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Repository\ProjectRepository;
use TimesheetBundle\Repository\Query\ProjectQuery;
use App\Entity\Project;
use App\Repository\ProjectRepository;
use App\Repository\Query\ProjectQuery;
/**
* Custom form field type to select a project.
@@ -33,7 +33,7 @@ class ProjectType extends AbstractType
{
$resolver->setDefaults([
'label' => 'label.project',
'class' => 'TimesheetBundle:Project',
'class' => 'Kimai:Project',
'choice_label' => 'name',
'group_by' => function (Project $project, $key, $index) {
return $project->getCustomer()->getName();

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@@ -32,7 +32,7 @@ class UserRoleType extends AbstractType
* UserRolesType constructor.
* @param string[] $roles
*/
public function __construct(array $roles)
public function __construct(array $roles = [])
{
$this->roles = $roles;
}

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use AppBundle\Entity\User;
use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -30,7 +30,7 @@ class UserType extends AbstractType
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'AppBundle:User',
'class' => 'Kimai:User',
'choice_label' => function (User $user) {
if (!empty($user->getAlias())) {
return $user->getAlias() . ' (' . $user->getUsername() . ')';

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use AppBundle\Repository\Query\VisibilityInterface;
use App\Repository\Query\VisibilityQuery;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -32,8 +32,8 @@ class VisibilityType extends AbstractType
$resolver->setDefaults([
'label' => 'label.visible',
'choices' => [
'yes' => VisibilityInterface::SHOW_VISIBLE,
'no' => VisibilityInterface::SHOW_HIDDEN,
'yes' => VisibilityQuery::SHOW_VISIBLE,
'no' => VisibilityQuery::SHOW_HIDDEN,
],
]);
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form\Type;
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
namespace App\Form;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
@@ -50,7 +50,7 @@ class UserCreateType extends UserEditType
public function __configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'AppBundle:User',
'class' => 'Kimai:User',
]);
}
}

View File

@@ -9,11 +9,11 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
namespace App\Form;
use AppBundle\Entity\User;
use AppBundle\Form\Type\LanguageType;
use AppBundle\Form\Type\YesNoType;
use App\Entity\User;
use App\Form\Type\LanguageType;
use App\Form\Type\YesNoType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
namespace App\Form;
use AppBundle\Entity\User;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;

View File

@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
namespace App\Form;
use AppBundle\Entity\User;
use AppBundle\Form\Type\UserRoleType;
use App\Entity\User;
use App\Form\Type\UserRoleType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

68
src/Kernel.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
namespace App;
use App\DependencyInjection\Compiler\DoctrineCompilerPass;
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\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function getCacheDir()
{
return $this->getProjectDir().'/var/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->getProjectDir().'/var/log';
}
public function registerBundles()
{
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
}
}
}
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
if (is_dir($confDir.'/packages/'.$this->environment)) {
$loader->load($confDir.'/packages/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
}
$loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
// TODO active doctrine-extensions
// composer require beberlei/DoctrineExtensions
// $container->addCompilerPass(new DoctrineCompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -1000);
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
if (is_dir($confDir.'/routes/')) {
$routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
}
if (is_dir($confDir.'/routes/'.$this->environment)) {
$routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
}
$routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
}
}

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model;
namespace App\Model;
/**
* Activity statistics

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model;
namespace App\Model;
/**
* Customer statistics

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model;
namespace App\Model;
/**
* Project statistics

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model\Statistic;
namespace App\Model\Statistic;
/**
* Yearly statistics

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model\Statistic;
namespace App\Model\Statistic;
/**
* Yearly statistics

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model;
namespace App\Model;
/**
* Timesheet statistics for all user.

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Model;
namespace App\Model;
use \DateTime;

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Model;
namespace App\Model;
/**
* User statistics

View File

@@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Repository;
namespace App\Repository;
use AppBundle\Repository\Query\BaseQuery;
use App\Repository\Query\BaseQuery;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;

View File

@@ -9,15 +9,14 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository;
namespace App\Repository;
use AppBundle\Entity\User;
use AppBundle\Repository\AbstractRepository;
use App\Entity\User;
use Doctrine\ORM\Query;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Timesheet;
use TimesheetBundle\Model\ActivityStatistic;
use TimesheetBundle\Repository\Query\ActivityQuery;
use App\Entity\Activity;
use App\Entity\Timesheet;
use App\Model\ActivityStatistic;
use App\Repository\Query\ActivityQuery;
/**
* Class ActivityRepository
@@ -46,7 +45,7 @@ class ActivityRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('t', 'a', 'p', 'c')
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->join('t.activity', 'a')
->join('a.project', 'p')
->join('p.customer', 'c')
@@ -89,7 +88,7 @@ class ActivityRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(a.id) FROM TimesheetBundle:Activity a')
->createQuery('SELECT COUNT(a.id) FROM '.Activity::class.' a')
->getSingleScalarResult();
$stats = new ActivityStatistic();
@@ -109,7 +108,7 @@ class ActivityRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(t.id) as totalRecords', 'SUM(t.duration) as totalDuration')
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->where('t.activity = :activity')
;
@@ -151,7 +150,7 @@ class ActivityRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('a', 'p', 'c')
->from('TimesheetBundle:Activity', 'a')
->from(Activity::class, 'a')
->join('a.project', 'p')
->join('p.customer', 'c')
->orderBy('a.' . $query->getOrderBy(), $query->getOrder());

View File

@@ -9,13 +9,15 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository;
namespace App\Repository;
use AppBundle\Repository\AbstractRepository;
use App\Entity\Activity;
use App\Entity\Project;
use App\Entity\Timesheet;
use Doctrine\ORM\Query;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Model\CustomerStatistic;
use TimesheetBundle\Repository\Query\CustomerQuery;
use App\Entity\Customer;
use App\Model\CustomerStatistic;
use App\Repository\Query\CustomerQuery;
/**
* Class CustomerRepository
@@ -43,7 +45,7 @@ class CustomerRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(c.id) FROM TimesheetBundle:Customer c')
->createQuery('SELECT COUNT(c.id) FROM '.Customer::class.' c')
->getSingleScalarResult();
$stats = new CustomerStatistic();
@@ -62,10 +64,10 @@ class CustomerRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(t.id) as recordAmount', 'SUM(t.duration) as recordDuration, COUNT(DISTINCT(a.id)) as activityAmount, COUNT(DISTINCT(p.id)) as projectAmount')
->from('TimesheetBundle:Timesheet', 't')
->join('TimesheetBundle:Activity', 'a')
->join('TimesheetBundle:Project', 'p')
->join('TimesheetBundle:Customer', 'c')
->from(Timesheet::class, 't')
->join(Activity::class, 'a')
->join(Project::class, 'p')
->join(Customer::class, 'c')
->andWhere('t.activity = a.id')
->andWhere('a.project = p.id')
->andWhere('p.customer = c.id')
@@ -114,7 +116,7 @@ class CustomerRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('c')
->from('TimesheetBundle:Customer', 'c')
->from(Customer::class, 'c')
->orderBy('c.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() == CustomerQuery::SHOW_VISIBLE) {

View File

@@ -9,13 +9,14 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository;
namespace App\Repository;
use AppBundle\Repository\AbstractRepository;
use App\Entity\Activity;
use App\Entity\Timesheet;
use Doctrine\ORM\Query;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Model\ProjectStatistic;
use TimesheetBundle\Repository\Query\ProjectQuery;
use App\Entity\Project;
use App\Model\ProjectStatistic;
use App\Repository\Query\ProjectQuery;
/**
* Class ProjectRepository
@@ -43,7 +44,7 @@ class ProjectRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(p.id) FROM TimesheetBundle:Project p')
->createQuery('SELECT COUNT(p.id) FROM '.Project::class.' p')
->getSingleScalarResult();
$stats = new ProjectStatistic();
@@ -62,8 +63,8 @@ class ProjectRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(t.id) as recordAmount', 'SUM(t.duration) as recordDuration, COUNT(DISTINCT(a.id)) as activityAmount')
->from('TimesheetBundle:Activity', 'a')
->join('TimesheetBundle:Timesheet', 't')
->from(Activity::class, 'a')
->join(Timesheet::class, 't')
->where('a.project = :project')
->andWhere('t.activity = a.id')
;
@@ -109,7 +110,7 @@ class ProjectRepository extends AbstractRepository
// if we join activities, the maxperpage limit will limit the list
// due to the raised amount of rows by projects * activities
$qb->select('p', 'c')
->from('TimesheetBundle:Project', 'p')
->from(Project::class, 'p')
->join('p.customer', 'c')
->orderBy('p.' . $query->getOrderBy(), $query->getOrder());

View File

@@ -9,22 +9,18 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository\Query;
namespace App\Repository\Query;
use AppBundle\Repository\Query\BaseQuery;
use AppBundle\Repository\Query\VisibilityInterface;
use AppBundle\Repository\Query\VisibilityTrait;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use App\Entity\Customer;
use App\Entity\Project;
/**
* Can be used for advanced queries with the: ActivityRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class ActivityQuery extends BaseQuery implements VisibilityInterface
class ActivityQuery extends VisibilityQuery
{
use VisibilityTrait;
/**
* @var Project

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Repository\Query;
namespace App\Repository\Query;
/**
* Base class for advanced Repository queries.

View File

@@ -9,18 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository\Query;
use AppBundle\Repository\Query\BaseQuery;
use AppBundle\Repository\Query\VisibilityInterface;
use AppBundle\Repository\Query\VisibilityTrait;
namespace App\Repository\Query;
/**
* Can be used for advanced queries with the: CustomerRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class CustomerQuery extends BaseQuery implements VisibilityInterface
class CustomerQuery extends VisibilityQuery
{
use VisibilityTrait;
}

View File

@@ -9,21 +9,17 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository\Query;
namespace App\Repository\Query;
use AppBundle\Repository\Query\BaseQuery;
use AppBundle\Repository\Query\VisibilityInterface;
use AppBundle\Repository\Query\VisibilityTrait;
use TimesheetBundle\Entity\Customer;
use App\Entity\Customer;
/**
* Can be used for advanced queries with the: ProjectRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class ProjectQuery extends BaseQuery implements VisibilityInterface
class ProjectQuery extends VisibilityQuery
{
use VisibilityTrait;
/**
* @var Customer

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository\Query;
namespace App\Repository\Query;
use AppBundle\Entity\User;
use AppBundle\Repository\Query\BaseQuery;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use App\Entity\User;
use App\Repository\Query\BaseQuery;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
/**
* Can be used for advanced timesheet repository queries.

View File

@@ -9,16 +9,15 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Repository\Query;
namespace App\Repository\Query;
/**
* Can be used for advanced queries with the: UserRepository
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class UserQuery extends BaseQuery implements VisibilityInterface
class UserQuery extends VisibilityQuery
{
use VisibilityTrait;
/**
* @var string

View File

@@ -9,15 +9,20 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Repository\Query;
namespace App\Repository\Query;
/**
* Can be used for advanced queries with the: UserRepository
* Query class for Repositories with a visibility field.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
trait VisibilityTrait
class VisibilityQuery extends BaseQuery
{
const SHOW_VISIBLE = 1;
const SHOW_HIDDEN = 2;
const SHOW_BOTH = 3;
/**
* @var integer
*/
@@ -41,9 +46,15 @@ trait VisibilityTrait
*/
public function setVisibility($visibility)
{
if (!is_int($visibility) && $visibility != (int) $visibility) {
return $this;
}
$visibility = (int) $visibility;
if (in_array($visibility, [self::SHOW_BOTH, self::SHOW_VISIBLE, self::SHOW_HIDDEN], true)) {
$this->visibility = $visibility;
}
return $this;
}
@@ -59,12 +70,11 @@ trait VisibilityTrait
* If set to true, this will ONLY filter the visibility on the main queried object.
*
* @param bool $exclusiveVisibility
* @return VisibilityTrait
* @return $this
*/
public function setExclusiveVisibility($exclusiveVisibility)
{
$this->exclusiveVisibility = (bool) $exclusiveVisibility;
return $this;
}
}

View File

@@ -9,20 +9,19 @@
* file that was distributed with this source code.
*/
namespace TimesheetBundle\Repository;
namespace App\Repository;
use AppBundle\Entity\User;
use AppBundle\Repository\AbstractRepository;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Timesheet;
use App\Entity\User;
use App\Entity\Activity;
use App\Entity\Timesheet;
use Doctrine\DBAL\Types\Type;
use Pagerfanta\Pagerfanta;
use TimesheetBundle\Model\Statistic\Month;
use TimesheetBundle\Model\Statistic\Year;
use TimesheetBundle\Model\TimesheetGlobalStatistic;
use TimesheetBundle\Model\TimesheetStatistic;
use App\Model\Statistic\Month;
use App\Model\Statistic\Year;
use App\Model\TimesheetGlobalStatistic;
use App\Model\TimesheetStatistic;
use DateTime;
use TimesheetBundle\Repository\Query\TimesheetQuery;
use App\Repository\Query\TimesheetQuery;
/**
* Class TimesheetRepository
@@ -98,7 +97,7 @@ class TimesheetRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select($select)
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->where($qb->expr()->gt('t.begin', ':from'))
->andWhere($qb->expr()->lt('t.end', ':to'))
->setParameter('from', $begin, Type::DATETIME)
@@ -122,11 +121,11 @@ class TimesheetRepository extends AbstractRepository
public function getUserStatistics(User $user)
{
$durationTotal = $this->getEntityManager()
->createQuery('SELECT SUM(t.duration) FROM TimesheetBundle:Timesheet t WHERE t.user = :user')
->createQuery('SELECT SUM(t.duration) FROM '.Timesheet::class.' t WHERE t.user = :user')
->setParameter('user', $user)
->getSingleScalarResult();
$rateTotal = $this->getEntityManager()
->createQuery('SELECT SUM(t.rate) FROM TimesheetBundle:Timesheet t WHERE t.user = :user')
->createQuery('SELECT SUM(t.rate) FROM '.Timesheet::class.' t WHERE t.user = :user')
->setParameter('user', $user)
->getSingleScalarResult();
$amountMonth = $this->queryThisMonth('SUM(t.rate)', $user)
@@ -136,7 +135,7 @@ class TimesheetRepository extends AbstractRepository
->getQuery()
->getSingleScalarResult();
$firstEntry = $this->getEntityManager()
->createQuery('SELECT MIN(t.begin) FROM TimesheetBundle:Timesheet t WHERE t.user = :user')
->createQuery('SELECT MIN(t.begin) FROM '.Timesheet::class.' t WHERE t.user = :user')
->setParameter('user', $user)
->getSingleScalarResult();
@@ -161,7 +160,7 @@ class TimesheetRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('SUM(t.rate) as rate, SUM(t.duration) as duration, MONTH(t.begin) as month, YEAR(t.begin) as year')
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->where($qb->expr()->gt('t.begin', '0'))
->andWhere($qb->expr()->isNotNull('t.end'))
->orderBy('year', 'DESC')
@@ -205,13 +204,13 @@ class TimesheetRepository extends AbstractRepository
public function getGlobalStatistics()
{
$durationTotal = $this->getEntityManager()
->createQuery('SELECT SUM(t.duration) FROM TimesheetBundle:Timesheet t')
->createQuery('SELECT SUM(t.duration) FROM '.Timesheet::class.' t')
->getSingleScalarResult();
$rateTotal = $this->getEntityManager()
->createQuery('SELECT SUM(t.rate) FROM TimesheetBundle:Timesheet t')
->createQuery('SELECT SUM(t.rate) FROM '.Timesheet::class.' t')
->getSingleScalarResult();
$userTotal = $this->getEntityManager()
->createQuery('SELECT COUNT(DISTINCT(t.user)) FROM TimesheetBundle:Timesheet t')
->createQuery('SELECT COUNT(DISTINCT(t.user)) FROM '.Timesheet::class.' t')
->getSingleScalarResult();
$activeNow = $this->getActiveEntries();
$amountMonth = $this->queryThisMonth('SUM(t.rate)')
@@ -247,7 +246,7 @@ class TimesheetRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('t', 'a', 'p', 'c')
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->join('t.activity', 'a')
->join('a.project', 'p')
->join('p.customer', 'c')
@@ -274,7 +273,7 @@ class TimesheetRepository extends AbstractRepository
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('t', 'a', 'p', 'c', 'u')
->from('TimesheetBundle:Timesheet', 't')
->from(Timesheet::class, 't')
->join('t.activity', 'a')
->join('t.user', 'u')
->join('a.project', 'p')

View File

@@ -9,10 +9,11 @@
* file that was distributed with this source code.
*/
namespace AppBundle\Repository;
namespace App\Repository;
use AppBundle\Model\UserStatistic;
use AppBundle\Repository\Query\UserQuery;
use App\Entity\User;
use App\Model\UserStatistic;
use App\Repository\Query\UserQuery;
/**
* Class UserRepository
@@ -31,7 +32,7 @@ class UserRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(u.id) FROM AppBundle:User u')
->createQuery('SELECT COUNT(u.id) FROM '.User::class.' u')
->getSingleScalarResult();
$stats = new UserStatistic();
@@ -39,6 +40,12 @@ class UserRepository extends AbstractRepository
return $stats;
}
/**
* Fetch a user by his username.
*
* @param $username
* @return null|User
*/
public function findByUsername($username)
{
return $this->findOneBy(['username' => $username]);
@@ -54,7 +61,7 @@ class UserRepository extends AbstractRepository
// if we join activities, the maxperpage limit will limit the list to the amount or projects + activties
$qb->select('u')
->from('AppBundle:User', 'u')
->from(User::class, 'u')
->orderBy('u.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() == UserQuery::SHOW_VISIBLE) {

View File

@@ -1,31 +0,0 @@
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle ddt-large ticktac" data-toggle="dropdown">
<i class="fa fa-play-circle fa-2x"></i>
{% if entries is not empty %}<span class="label label-{% if entries|length >= kimai_context.active_warning %}warning{% else %}success{% endif %}">{{ entries|length }}</span>{% endif %}
</a>
<ul class="dropdown-menu">
<li class="header">
{{ 'active.entries'|transchoice(entries|length) }}
</li>
<li>
<ul class="menu">
{% for entry in entries %}
<li>
<a href="{{ path('timesheet_stop', {'id' : entry.id}) }}">
<div class="pull-left">
<i class="fa fa-stop-circle fa-2x"></i>
</div>
<h4>
{{ entry.activity.name }}
<small><i class="fa fa-clock-o"></i> {{ entry|durationForEntry }}</small>
</h4>
<p>{{ entry.activity.project.name }} ({{ entry.activity.project.customer.name }})</p>
</a>
</li>
{% endfor %}
</ul>
</li>
<li class="footer"><a href="{{ path('timesheet_create') }}">{{ 'timesheet.start'|trans }}</a></li>
</ul>
</li>

View File

@@ -1,23 +0,0 @@
{% if activities is not empty %}
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle ddt-large" data-toggle="dropdown">
<i class="fa fa-tasks fa-2x"></i>
<span class="label label-success">{{ activities|length }}</span>
</a>
<ul class="dropdown-menu">
<li class="header">{{ 'recent.activities'|transchoice(activities|length) }}</li>
<li>
<ul class="menu">
{% for activity in activities %}
<li>
<a href="{{ path('timesheet_start', {'id' : activity.id}) }}">
<i class="fa fa-play-circle text-green"></i> {{ 'recent.activities.format'|trans({'%activity%': activity.name, '%project%': activity.project.name, '%customer%': activity.project.customer.name}) }}
</a>
</li>
{% endfor %}
</ul>
</li>
<li class="footer"><a href="{{ url('timesheet') }}">{{ 'timesheet.all'|trans }}</a></li>
</ul>
</li>
{% endif %}

View File

@@ -1,48 +0,0 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.name': '',
'label.customer': '',
'label.project': '',
'label.comment': 'hidden-xs',
'label.visible': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_activity_create')}) }}
{% for entry in entries %}
<tr>
<td>{{ entry.name }}</td>
<td>
<a href="{{ path('admin_customer_edit', {'id' : entry.project.customer.id}) }}">{{ widgets.label_customer(entry.project.customer) }}</a>
</td>
<td>
<a href="{{ path('admin_project_edit', {'id' : entry.project.id}) }}">{{ widgets.label_project(entry.project) }}</a>
</td>
<td class="hidden-xs">{{ entry.comment }}</td>
<td>{{ widgets.label_visible(entry.visible) }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_activity_edit', {'id': entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_activity_delete', {'id': entry.id})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_activity_paginated') }}
{% endblock %}

View File

@@ -1,24 +0,0 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }}{% endblock %}
{% block main %}
{% set params = {
'%activity%': '<strong>' ~ activity.name ~ '</strong>',
'%project%': '<strong>' ~ activity.project.name ~ '</strong>',
'%customer%': '<strong>' ~ activity.project.customer.name ~ '</strong>',
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
} %}
{{ include('default/_form_delete.html.twig', {
'message': "admin_activity.delete_confirm"|trans(params)|raw,
'form': form,
'back': path('admin_activity')
}) }}
{% endblock %}

View File

@@ -1,14 +0,0 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': activity.name|default('create'|trans),
'form': form,
'back': path('admin_activity')
}) }}
{% endblock %}

View File

@@ -1,54 +0,0 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{# Available fields: vat; contact; address; country; phone; fax; mobile; mail; homepage; timezone; #}
{{ tables.data_table_header({
'label.id': 'hidden-xs',
'label.name': '',
'label.project': '',
'label.comment': 'hidden-xs',
'label.country': 'hidden-xs',
'label.currency': 'hidden-xs',
'label.visible': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_customer_create')}) }}
{% for entry in entries %}
<tr>
<td class="hidden-xs">{{ entry.id }}</td>
<td>{{ entry.name }} {% if entry.company is not empty %}({{ entry.company }}){% endif %}</td>
<td>
{% for project in entry.projects %}
<a href="{{ path('admin_project_edit', {'id' : project.id}) }}">{{ widgets.label_project(project) }}</a>
{% endfor %}
</td>
<td class="hidden-xs">{{ entry.comment }}</td>
<td class="hidden-xs">{{ entry.country|country }}</td>
<td class="hidden-xs">{{ entry.currency }} {{ entry.currency|currency }}</td>
<td>{{ widgets.label_visible(entry.visible) }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_customer_edit', {'id': entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_customer_delete', {'id': entry.id})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_customer_paginated') }}
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More