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

29
.env.dist Normal file
View File

@@ -0,0 +1,29 @@
# This file is a "template" of which env vars need to be defined for your application
# Copy this file to .env file for development, create environment variables when deploying to production
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
# KIMAI DEFAULT ENV VARS
DATABASE_PREFIX=kimai2_
DATABASE_ENGINE=sqlite
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/kimai.sqlite
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=c88c14fa70a424e7a12d459b9dd9df7f
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS=localhost,example.com
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data/kimai.sqlite"
# Configure your db driver and server_version in config/packages/doctrine.yaml
#DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
###< doctrine/doctrine-bundle ###
###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###

68
.gitignore vendored
View File

@@ -1,57 +1,39 @@
# Cache and logs (Symfony2) ###> symfony/framework-bundle ###
/app/cache/* .env
/app/logs/* /public/bundles/
!app/cache/.gitkeep /vendor/
!app/logs/.gitkeep ###< symfony/framework-bundle ###
# Email spool folder ###> symfony/web-server-bundle ###
/app/spool/* .web-server-pid
###< symfony/web-server-bundle ###
# Cache, session files and logs (Symfony3) # ========== KIMAI ==========
/var/cache/*
/var/logs/*
/var/sessions/*
!var/cache/.gitkeep
!var/logs/.gitkeep
!var/sessions/.gitkeep
# Parameters
/app/config/parameters.yml
/app/config/parameters.ini
# Managed by Composer
/app/bootstrap.php.cache
/var/bootstrap.php.cache
/bin/* /bin/*
!bin/console !bin/console
!bin/symfony_requirements
/vendor/
# Assets and user uploads /public/theme/
/web/bundles/
/web/uploads/
# Assets managed by Bower /var/data/*.sqlite
/web/assets/vendor/
# PHPUnit /var/cache/*
/app/phpunit.xml !var/cache/.gitkeep
/phpunit.xml
# Build data /var/log/*
/build/ !var/log/.gitkeep
# Composer PHAR /var/sessions/*
/composer.phar !var/sessions/.gitkeep
# ========== KIMAI ==========
# Backup entities generated with doctrine:generate:entities command
*/Entity/*~
# IDE # IDE
.idea/ .idea/
# SQLite files ###> phpunit/phpunit ###
/app/data/timesheet.sqlite /phpunit.xml
###< phpunit/phpunit ###
# generated install and setup files ###> friendsofphp/php-cs-fixer ###
/web/theme/ .php_cs
.php_cs.cache
###< friendsofphp/php-cs-fixer ###

8
.php_cs.dist Normal file
View File

@@ -0,0 +1,8 @@
<?php
return PhpCsFixer\Config::create()
->setRules([
'@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
])
;

View File

@@ -9,14 +9,13 @@ Kimai v2 - the reloaded open source Time-Tracking application.
This is (or will be in the future, currently a lot of features are still missing) the reloaded version of the open source time-tracking application [Kimai](http://www.kimai.org). This is (or will be in the future, currently a lot of features are still missing) the reloaded version of the open source time-tracking application [Kimai](http://www.kimai.org).
It is based on the following PHP components: It is based on the following PHP components:
- [Symfony Framework 3.4](https://github.com/symfony/symfony) - [Symfony Framework 4](https://github.com/symfony/symfony)
- [AdminThemeBundle](https://github.com/avanzu/AdminThemeBundle/) (based on [AdminLTE](https://github.com/almasaeed2010/AdminLTE/)) - [AdminThemeBundle](https://github.com/avanzu/AdminThemeBundle/) (based on [AdminLTE](https://github.com/almasaeed2010/AdminLTE/))
- [Doctrine](https://github.com/doctrine/) - [Doctrine](https://github.com/doctrine/)
- Bower
## Requirements ## Requirements
- PHP 7 or higher - PHP 7.1 or higher
- One PHP extension of PDO-SQLite and/or PDO-MySQL enabled - One PHP extension of PDO-SQLite and/or PDO-MySQL enabled
- and the [usual Symfony application requirements](http://symfony.com/doc/current/reference/requirements.html) - and the [usual Symfony application requirements](http://symfony.com/doc/current/reference/requirements.html)
@@ -53,13 +52,13 @@ All thats left to do is to create your first user:
$ bin/console kimai:create-user admin admin@example.com password en ROLE_SUPER_ADMIN $ bin/console kimai:create-user admin admin@example.com password en ROLE_SUPER_ADMIN
``` ```
For available roles, please refer to [the user documentation](app/Resources/docs/users.md). For available roles, please refer to [the user documentation](var/docs/users.md).
### Installation (development / demo) ### Installation (development / demo)
Lets boostrap your environment by executing this commands (which is only available in dev environment): Lets boostrap your environment by executing this commands (which is only available in dev environment):
```bash ```bash
$ bin/console kimai:dev:reset $ bin/console kimai:reset-dev
``` ```
You just imported demo data, to test the application in its full beauty and with several different user accounts and permission sets. You just imported demo data, to test the application in its full beauty and with several different user accounts and permission sets.
@@ -83,7 +82,7 @@ $ bin/console doctrine:schema:drop --force
$ bin/console doctrine:schema:create $ bin/console doctrine:schema:create
``` ```
The `kimai:dev:reset` command can always be executed later on to reset your dev database and cache. I use it very frequently. The `kimai:reset-dev` command can always be executed later on to reset your dev database and cache. I use it very frequently.
## Usage ## Usage

View File

@@ -1,26 +0,0 @@
{
"name": "Kimai v2",
"description": "The reloaded Kimai Time-tracking application",
"keywords": [
"php",
"kimai"
],
"website": "https://www.kimai.org.com/",
"repository": "https://github.com/kevinpapst/kimai2",
"logo": "",
"success_url": "/",
"scripts": {
"postdeploy": "php bin/console doctrine:schema:create && php bin/console doctrine:fixtures:load -n"
},
"env": {
"SYMFONY_ENV": "prod",
"SYMFONY_SECRET": {
"description": "Extra entropy for %kernel.secret%; used for CSRF tokens, cookies and signed URLs.",
"generator": "secret"
}
},
"addons": [
"heroku-postgresql"
],
"image": "heroku/php"
}

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,71 +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.
*/
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
/**
* Class AppKernel
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
new Avanzu\AdminThemeBundle\AvanzuAdminThemeBundle(),
new AppBundle\AppBundle(),
new TimesheetBundle\TimesheetBundle(),
];
// Bundles only used for development or unit and functional tests
if (in_array($this->getEnvironment(), ['dev', 'test'])) {
//$bundles[] = new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle();
$bundles[] = new Symfony\Bundle\AsseticBundle\AsseticBundle();
$bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle();
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
$bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle();
}
return $bundles;
}
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
}
public function getLogDir()
{
return dirname(__DIR__).'/var/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
}

View File

@@ -1,13 +0,0 @@
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Composer\Autoload\ClassLoader;
/**
* @var ClassLoader $loader
*/
$loader = require __DIR__.'/../vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
return $loader;

View File

@@ -1,105 +0,0 @@
# This is the main configuration file of your application. It stores all the
# common options for every execution environment ('prod', 'dev', 'test').
# To avoid creating configuration files that are too long, we first import some
# files that define the values for important parts of the application,
# such as the security component and the dependency injection services
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# These are the configuration parameters that define the application's behavior
# and which are independent from the underlying technical infrastructure
# See http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
# This parameter defines the codes of the locales (languages) enabled in the application
app_locales: en|de
app.notifications.email_sender: "%mailer_from%"
# Basic configuration for the Symfony framework features
framework:
# Uncomment the 'ide' option to turn all of the file paths in an exception
# page into clickable links that open the given file using your favorite IDE.
# Supported values are 'textmate', 'macvim', 'emacs' and 'sublime' shortcuts
# and any custom configuration string, such as: "phpstorm://open?file=%%f&line=%%l"
# See http://symfony.com/doc/current/reference/configuration/framework.html#ide
#ide: sublime
# When using the HTTP Cache, ESI allows to render page fragments separately
# and with different cache configurations for each fragment
# http://symfony.com/doc/current/book/http_cache.html#edge-side-includes
esi: { enabled: true }
translator: { fallback: "%locale%" }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
session:
handler_id: session.handler.native_file
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
# Twig Configuration (used for rendering application templates)
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# form_themes:
# - "bootstrap_3_layout.html.twig"
# - "form/fields.html.twig"
globals:
kimai_context:
date_1: "d.m.Y" # used for display in timesheets
box_color: "green" # a color for ???
active_warning: 3 # display a warning color if the user has at least X active recordings
# Assetic Configuration (used for managing web assets: CSS, JavaScript, Sass, etc.)
#assetic:
# debug: "%kernel.debug%"
# use_controller: false
# bundles: [ ]
# filters:
# cssrewrite: ~
# jsqueeze: ~
# scssphp:
# # the formatter must be the FQCN (don't use the 'compressed' value)
# formatter: "Leafo\\ScssPhp\\Formatter\\Compressed"
# Doctrine Configuration (used to access databases and manipulate their information)
doctrine:
dbal:
url: "%database_url%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
# Swiftmailer Configuration (used to send emails)
#swiftmailer:
# transport: "%mailer_transport%"
# host: "%mailer_host%"
# username: "%mailer_user%"
# password: "%mailer_password%"
# spool: { type: memory }
avanzu_admin_theme:
use_twig: true
use_assetic: true
bower_bin: "/usr/local/bin/bower"
options:
default_avatar: avatars/default.png
skin: skin-green-light
fixed_layout: false
boxed_layout: false
collapsed_sidebar: true
mini_sidebar: true
control_sidebar: false

View File

@@ -1,47 +0,0 @@
imports:
- { resource: config.yml }
- { resource: services_dev.yml }
framework:
router:
resource: "%kernel.root_dir%/config/routing_dev.yml"
strict_requirements: true
profiler: { only_exceptions: false }
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: info
console:
type: console
bubble: false
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
#assetic:
# use_controller: true
#swiftmailer:
# delivery_address: me@example.com
services:
twig.text_extension:
class: Twig_Extensions_Extension_Text
tags:
- name: twig.extension
web_profiler:
toolbar: '%kernel.debug%'
intercept_redirects: false
# See routing_dev.yml
#avanzu_admin_theme:
# enable_demo: false

View File

@@ -1,25 +0,0 @@
imports:
- { resource: config.yml }
#framework:
# cache:
# system: cache.adapter.apcu
#doctrine:
# orm:
# metadata_cache_driver: apc
# result_cache_driver: apc
# query_cache_driver: apc
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console

View File

@@ -1,31 +0,0 @@
imports:
- { resource: config_dev.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
profiler:
collect: false
web_profiler:
toolbar: false
intercept_redirects: false
swiftmailer:
disable_delivery: true
# It's recommended to use a separate database for tests. This allows to have a
# fixed and known set of data fixtures, it simplifies the code of tests and it
# makes them more robust.
# In this case we just need to define a different path for the application database.
doctrine:
dbal:
database_url: 'sqlite:///%kernel.root_dir%/data/timesheet_test.sqlite'
# this configuration simplifies testing URLs protected by the security mechanism
# See http://symfony.com/doc/current/cookbook/testing/http_authentication.html
security:
firewalls:
secured_area:
http_basic: ~

View File

@@ -1,37 +0,0 @@
# This file defines the canonical configuration parameters of the application.
# Symfony uses this file as a template to generate the real app/config/parameters.yml used by the application.
# See http://symfony.com/doc/current/best_practices/configuration.html#canonical-parameters
parameters:
# used to load additional doctrine functions (possible values: mysql, sqlite)
database_engine: sqlite
# Define the database connection string
database_url: 'sqlite:///%kernel.root_dir%/data/timesheet.sqlite'
# database_url: 'mysql://root:pass@127.0.0.1:3306/timesheet'
# You can prefix all your tables to pevent collision with other software
database_prefix: kimai2_
# You can create the database and load the sample data from the command line:
#
# php bin/console doctrine:database:create
# php bin/console doctrine:schema:create
# php bin/console doctrine:fixtures:load
# If you don't use a real mail server, you can send emails via your Gmail account.
# see http://symfony.com/doc/current/cookbook/email/gmail.html
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: ~
mailer_password: ~
mailer_from: anonymous@example.com
# The code of the default language used by the application ('en' = English, 'de' = German)
locale: de
# The 'secret' value is a random string of characters, numbers and symbols
# used internally by Symfony in several places (CSRF tokens, URI signing,
# 'Remember Me' functionality, etc.)
# see: http://symfony.com/doc/current/reference/configuration/framework.html#secret
secret: 'please_change_this_secret_to_something_unique'

View File

@@ -1,39 +0,0 @@
# These first lines load the all routes defined as @Route() annotations in any
# controller defined inside the src/AppBundle/Controller/ directory. Controllers
# are loaded recursively, so you can separate them into subdirectories.
# If you don't like to add annotations in your applications, you can also define
# the routes in YAML, XML or PHP files.
# See http://symfony.com/doc/current/book/routing.html
app:
resource: '@AppBundle/Controller/'
type: annotation
prefix: /{_locale}
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'
timesheet:
resource: '@TimesheetBundle/Controller/'
type: annotation
prefix: /{_locale}
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'
# These lines define a route using YAML configuration. The controller used by
# the route (FrameworkBundle:Template:template) is a convenient shortcut when
# the template can be rendered without executing any logic in your own controller.
# See http://symfony.com/doc/current/cookbook/templating/render_without_controller.html
homepage:
path: /{_locale}
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: timesheet
permanent: true
avanzu_admin_profile:
path: /{_locale}/profile/{username}
options:
avanzu_admin_route: profile

View File

@@ -1,35 +0,0 @@
# this imports the routes used to display the web debug toolbar at the bottom of each page
_wdt:
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
prefix: /_wdt
# this imports the routes needed to display the Symfony Profiler information
_profiler:
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
prefix: /_profiler
# this imports the route used to test error pages. Just browse the following URL:
# /{_locale}/_error/{status_code}.{format}
# (e.g. /en/_error/404, /en/_error/403.json, /fr/_error/500.xml)
# See http://symfony.com/doc/current/cookbook/controller/error_pages.html#testing-error-pages-during-development
_errors:
resource: "@TwigBundle/Resources/config/routing/errors.xml"
prefix: /{_locale}/_error
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'
# this loads the main routing file, which usually defines the routes available
# in any environment (production, development, etc.)
_main:
resource: routing.yml
# ========================================================================
# Demo routes, only work with "avanzu_admin_theme/enable_demo: true"
# ========================================================================
#avanzu_admin:
# prefix: /admin
# resource: "@AvanzuAdminThemeBundle/Resources/config/routes.yml"

View File

@@ -1,32 +0,0 @@
imports:
- { resource: services.yml }
services:
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
app.command.run_phpcs:
class: AppBundle\Command\RunCodeSnifferCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:phpcs }
app.command.run_unit_tests:
class: AppBundle\Command\RunUnitTestsCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:test-unit }
app.command.run_integration_tests:
class: AppBundle\Command\RunIntegrationTestsCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:test-integration }
app.command.dev_reset:
class: AppBundle\Command\DevResetCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:reset }

View File

@@ -1,29 +1,39 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug; use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
//umask(0000);
set_time_limit(0); set_time_limit(0);
/** require __DIR__.'/../vendor/autoload.php';
* @var Composer\Autoload\ClassLoader $loader
*/
$loader = require __DIR__.'/../app/autoload.php';
$input = new ArgvInput(); if (!class_exists(Application::class)) {
$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
if ($debug) {
Debug::enable();
} }
$kernel = new AppKernel($env, $debug); if (!isset($_SERVER['APP_ENV'])) {
if (!class_exists(Dotenv::class)) {
throw new \RuntimeException('APP_ENV environment variable is not defined. You need to define environment variables for configuration or add "symfony/dotenv" as a Composer dependency to load variables from a .env file.');
}
(new Dotenv())->load(__DIR__.'/../.env');
}
$input = new ArgvInput();
$env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev');
$debug = ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption(['--no-debug', '']);
if ($debug) {
umask(0000);
if (class_exists(Debug::class)) {
Debug::enable();
}
}
$kernel = new Kernel($env, $debug);
$application = new Application($kernel); $application = new Application($kernel);
$application->run($input); $application->run($input);

View File

@@ -1,146 +0,0 @@
#!/usr/bin/env php
<?php
require_once dirname(__FILE__).'/../var/SymfonyRequirements.php';
$lineSize = 70;
$symfonyRequirements = new SymfonyRequirements();
$iniPath = $symfonyRequirements->getPhpIniConfigPath();
echo_title('Symfony Requirements Checker');
echo '> PHP is using the following php.ini file:'.PHP_EOL;
if ($iniPath) {
echo_style('green', ' '.$iniPath);
} else {
echo_style('yellow', ' WARNING: No configuration file (php.ini) used by PHP!');
}
echo PHP_EOL.PHP_EOL;
echo '> Checking Symfony requirements:'.PHP_EOL.' ';
$messages = array();
foreach ($symfonyRequirements->getRequirements() as $req) {
if ($helpText = get_error_message($req, $lineSize)) {
echo_style('red', 'E');
$messages['error'][] = $helpText;
} else {
echo_style('green', '.');
}
}
$checkPassed = empty($messages['error']);
foreach ($symfonyRequirements->getRecommendations() as $req) {
if ($helpText = get_error_message($req, $lineSize)) {
echo_style('yellow', 'W');
$messages['warning'][] = $helpText;
} else {
echo_style('green', '.');
}
}
if ($checkPassed) {
echo_block('success', 'OK', 'Your system is ready to run Symfony projects');
} else {
echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects');
echo_title('Fix the following mandatory requirements', 'red');
foreach ($messages['error'] as $helpText) {
echo ' * '.$helpText.PHP_EOL;
}
}
if (!empty($messages['warning'])) {
echo_title('Optional recommendations to improve your setup', 'yellow');
foreach ($messages['warning'] as $helpText) {
echo ' * '.$helpText.PHP_EOL;
}
}
echo PHP_EOL;
echo_style('title', 'Note');
echo ' The command console could use a different php.ini file'.PHP_EOL;
echo_style('title', '~~~~');
echo ' than the one used with your web server. To be on the'.PHP_EOL;
echo ' safe side, please check the requirements from your web'.PHP_EOL;
echo ' server using the ';
echo_style('yellow', 'web/config.php');
echo ' script.'.PHP_EOL;
echo PHP_EOL;
exit($checkPassed ? 0 : 1);
function get_error_message(Requirement $requirement, $lineSize)
{
if ($requirement->isFulfilled()) {
return;
}
$errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL;
$errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL;
return $errorMessage;
}
function echo_title($title, $style = null)
{
$style = $style ?: 'title';
echo PHP_EOL;
echo_style($style, $title.PHP_EOL);
echo_style($style, str_repeat('~', strlen($title)).PHP_EOL);
echo PHP_EOL;
}
function echo_style($style, $message)
{
// ANSI color codes
$styles = array(
'reset' => "\033[0m",
'red' => "\033[31m",
'green' => "\033[32m",
'yellow' => "\033[33m",
'error' => "\033[37;41m",
'success' => "\033[37;42m",
'title' => "\033[34m",
);
$supports = has_color_support();
echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : '');
}
function echo_block($style, $title, $message)
{
$message = ' '.trim($message).' ';
$width = strlen($message);
echo PHP_EOL.PHP_EOL;
echo_style($style, str_repeat(' ', $width));
echo PHP_EOL;
echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT));
echo PHP_EOL;
echo_style($style, $message);
echo PHP_EOL;
echo_style($style, str_repeat(' ', $width));
echo PHP_EOL;
}
function has_color_support()
{
static $support;
if (null === $support) {
if (DIRECTORY_SEPARATOR == '\\') {
$support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
} else {
$support = function_exists('posix_isatty') && @posix_isatty(STDOUT);
}
}
return $support;
}

View File

@@ -1,81 +1,87 @@
{ {
"name": "keleo/kimai", "name": "kimai/kimai",
"license": "MIT", "license": "MIT",
"type": "project", "type": "project",
"description": "Kimai Time Tracking reloaded", "description": "Kimai Time Tracking reloaded",
"autoload": {
"psr-4": {
"": "src/",
"KimaiTest\\": "tests/"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"require": { "require": {
"php": ">=7.0.8", "php": "^7.1.3",
"ext-pdo_sqlite": "*", "ext-pdo_sqlite": "*",
"doctrine/doctrine-bundle": "^1.6", "avanzu/admin-theme-bundle": "dev-master",
"doctrine/doctrine-fixtures-bundle": "^2.2",
"doctrine/orm": "^2.5",
"erusev/parsedown": "^1.5",
"ezyang/htmlpurifier": "^4.7",
"incenteev/composer-parameter-handler": "^2.0",
"leafo/scssphp": "^0.5",
"patchwork/jsqueeze": "^2.0",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0",
"symfony/assetic-bundle": "^2.8",
"symfony/monolog-bundle": "^3.1",
"symfony/swiftmailer-bundle": "^2.3",
"symfony/symfony": "~3.4",
"twig/extensions": "^1.3",
"white-october/pagerfanta-bundle": "^1.0",
"beberlei/DoctrineExtensions": "^1.0", "beberlei/DoctrineExtensions": "^1.0",
"symfony/web-server-bundle": "3.4", "dama/doctrine-test-bundle": "^4.0",
"avanzu/admin-theme-bundle": "dev-master" "sensio/framework-extra-bundle": "^5.1",
"symfony/asset": "^4.0",
"symfony/console": "^4.0",
"symfony/expression-language": "^4.0",
"symfony/flex": "^1.0",
"symfony/form": "^4.0",
"symfony/framework-bundle": "^4.0",
"symfony/lts": "^4@dev",
"symfony/monolog-bundle": "^3.1",
"symfony/orm-pack": "^1.0",
"symfony/profiler-pack": "^1.0",
"symfony/security-bundle": "^4.0",
"symfony/security-csrf": "^4.0",
"symfony/swiftmailer-bundle": "^3.1",
"symfony/translation": "^4.0",
"symfony/twig-bundle": "^4.0",
"symfony/validator": "^4.0",
"symfony/yaml": "^4.0",
"twig/extensions": "^1.5",
"white-october/pagerfanta-bundle": "^1.1"
}, },
"require-dev": { "require-dev": {
"sensio/generator-bundle": "~3.0", "doctrine/doctrine-fixtures-bundle": "^3.0",
"symfony/phpunit-bridge": "^3.0", "friendsofphp/php-cs-fixer": "^2.10",
"squizlabs/php_codesniffer": "3.*", "phpunit/phpunit": "^6.5",
"phpunit/phpunit": "^6" "squizlabs/php_codesniffer": "^3.2",
}, "symfony/debug-pack": "^1.0",
"scripts": { "symfony/dotenv": "^4.0",
"post-install-cmd": [ "symfony/maker-bundle": "^1.0",
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", "symfony/phpunit-bridge": "^4.0",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", "symfony/web-server-bundle": "^4.0"
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
]
}, },
"config": { "config": {
"bin-dir": "bin" "preferred-install": {
"*": "dist"
},
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php71": "*",
"symfony/polyfill-php70": "*",
"symfony/polyfill-php56": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
}, },
"extra": { "extra": {
"symfony-app-dir": "app", "symfony": {
"symfony-bin-dir": "bin", "id": "01C3FWRDJJEX9K6Y3A4XDFXPBR",
"symfony-var-dir": "var", "allow-contrib": false
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"incenteev-parameters": {
"file": "app/config/parameters.yml",
"env-map": {
"database_url": "DATABASE_URL",
"secret": "SYMFONY_SECRET"
}
} }
} }
} }

4609
composer.lock generated

File diff suppressed because it is too large Load Diff

20
config/bundles.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
Avanzu\AdminThemeBundle\AvanzuAdminThemeBundle::class => ['all' => true],
WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
];

View File

@@ -0,0 +1,14 @@
avanzu_admin_theme:
use_twig: true
use_assetic: true
bower_bin: "/usr/local/bin/bower"
options:
default_avatar: images/default_avatar.png
skin: skin-green-light
fixed_layout: false
boxed_layout: false
collapsed_sidebar: true
mini_sidebar: true
control_sidebar: false
knp_menu:
enable: false

View File

@@ -0,0 +1,16 @@
services:
EasyCorp\EasyLog\EasyLogHandler:
public: false
arguments: ['%kernel.logs_dir%/%kernel.environment%.log']
#// FIXME: How to add this configuration automatically without messing up with the monolog configuration?
#monolog:
# handlers:
# buffered:
# type: buffer
# handler: easylog
# channels: ['!event']
# level: debug
# easylog:
# type: service
# id: EasyCorp\EasyLog\EasyLogHandler

View File

@@ -0,0 +1,19 @@
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]

View File

@@ -0,0 +1,3 @@
framework:
router:
strict_requirements: true

View File

@@ -0,0 +1,4 @@
# See https://symfony.com/doc/current/email/dev_environment.html
swiftmailer:
# send all emails to a specific address
#delivery_addresses: ['me@example.com']

View File

@@ -0,0 +1,6 @@
web_profiler:
toolbar: true
intercept_redirects: false
framework:
profiler: { only_exceptions: false }

View File

@@ -0,0 +1,27 @@
parameters:
# Adds a fallback DATABASE_URL if the env var is not set.
# This allows you to run cache:warmup even if your
# environment variables are not available yet.
# You should not need to change this value.
env(DATABASE_URL): ''
doctrine:
dbal:
# configure these for your database server
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
# With Symfony 3.3, remove the `resolve:` prefix
url: '%env(resolve:DATABASE_URL)%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Kimai

View File

@@ -0,0 +1,5 @@
doctrine_migrations:
dir_name: '%kernel.project_dir%/src/Migrations'
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
namespace: DoctrineMigrations

View File

@@ -0,0 +1,26 @@
framework:
secret: '%env(APP_SECRET)%'
default_locale: en
csrf_protection: ~
#http_method_override: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: session.handler.native_file
save_path: "%kernel.project_dir%/var/sessions/%kernel.environment%"
#esi: ~
#fragments: ~
php_errors:
log: true
cache:
# The app cache caches to the filesystem by default. Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu

View File

@@ -0,0 +1,9 @@
twig:
# form_themes:
# - "bootstrap_3_layout.html.twig"
# - "form/fields.html.twig"
globals:
kimai_context:
date_1: "d.m.Y" # used for display in timesheets
box_color: "green" # a color for ???
active_warning: 3 # display a warning color if the user has at least X active recordings

View File

@@ -0,0 +1,31 @@
doctrine:
orm:
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

View File

@@ -0,0 +1,17 @@
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_404s:
# regex: exclude all 404 errors from the logs
- ^/
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]

View File

@@ -0,0 +1,3 @@
framework:
router:
strict_requirements: ~

View File

@@ -1,17 +1,17 @@
security: security:
encoders: encoders:
# Our user class and the algorithm we'll use to encode passwords App\Entity\User: bcrypt
# http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
AppBundle\Entity\User: bcrypt
# https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers: providers:
# in this example, users are stored via Doctrine in the database
# demo users can be found at src/AppBundle/DataFixtures/ORM/LoadFixtures.php
database_users: database_users:
entity: { class: AppBundle:User, property: username } entity: { class: App\Entity\User, property: username }
# http://symfony.com/doc/current/book/security.html#firewalls-authentication
firewalls: firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area: secured_area:
# does what it says # does what it says
logout_on_user_change: true logout_on_user_change: true
@@ -53,3 +53,4 @@ security:
- { path: '^/(%app_locales%)$', role: IS_AUTHENTICATED_FULLY } - { path: '^/(%app_locales%)$', role: IS_AUTHENTICATED_FULLY }
- { path: '^/(%app_locales%)/login', role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: '^/(%app_locales%)/login', role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: '^/(%app_locales%)/admin', roles: ROLE_ADMIN } - { path: '^/(%app_locales%)/admin', roles: ROLE_ADMIN }

View File

@@ -0,0 +1,3 @@
swiftmailer:
url: '%env(MAILER_URL)%'
spool: { type: 'memory' }

View File

@@ -0,0 +1,4 @@
framework:
test: ~
session:
storage_id: session.storage.mock_file

View File

@@ -0,0 +1,7 @@
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]

View File

@@ -0,0 +1,2 @@
swiftmailer:
disable_delivery: true

View File

@@ -0,0 +1,6 @@
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }

View File

@@ -0,0 +1,7 @@
framework:
default_locale: '%locale%'
translator:
paths:
- '%kernel.project_dir%/translations'
fallbacks:
- '%locale%'

11
config/packages/twig.yaml Normal file
View File

@@ -0,0 +1,11 @@
twig:
#paths: ['%kernel.project_dir%/templates']
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
# TODO move me to kimai config
globals:
kimai_context:
date_1: "d.m.Y" # used for display in timesheets
box_color: "green" # a color for ???
active_warning: 3 # display a warning color if the user has at least X active recordings

View File

@@ -0,0 +1,12 @@
services:
_defaults:
public: false
autowire: true
autoconfigure: true
#Twig\Extensions\ArrayExtension: ~
#Twig\Extensions\DateExtension: ~
Twig\Extensions\IntlExtension: ~
#Twig\Extensions\TextExtension: ~
Twig\Extensions\StringLoader:
class: Twig_Extension_StringLoader

11
config/routes.yaml Normal file
View File

@@ -0,0 +1,11 @@
homepage:
path: /{_locale}
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: timesheet
permanent: true
avanzu_admin_profile:
path: /{_locale}/profile/{username}
options:
avanzu_admin_route: profile

View File

@@ -0,0 +1,8 @@
controllers:
resource: '../src/Controller/'
type: annotation
prefix: /{_locale}
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'

View File

@@ -0,0 +1,8 @@
# ========================================================================
# Demo routes, only work with "avanzu_admin_theme/enable_demo: true"
# ========================================================================
#avanzu_admin:
# prefix: /admin
# resource: "@AvanzuAdminThemeBundle/Resources/config/routes.yml"

View File

@@ -0,0 +1,7 @@
_errors:
resource: '@TwigBundle/Resources/config/routing/errors.xml'
prefix: /_error
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'

View File

@@ -0,0 +1,7 @@
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler

View File

@@ -1,87 +1,50 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
app_locales: en|de
services: services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
# ================================================================================ # ================================================================================
# TWIG # APPLICATION CORE
# ================================================================================ # ================================================================================
markdown: # a route listener, that injects the locale through a URL directory
class: AppBundle\Utils\Markdown app.redirect_to_preferred_locale_listener:
class: App\EventListener\RedirectToPreferredLocaleListener
app.twig.app_extension: arguments: ['@router', '%app_locales%', '%locale%']
public: false
class: AppBundle\Twig\Extensions
arguments: ['@markdown', '%app_locales%']
tags: tags:
- { name: twig.extension } - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
# twig function: template_from_string() # additional menu entries for the timesheet bundle
app.twig.loader_extension: timesheet.configure_menu_listener:
class: Twig_Extension_StringLoader class: App\EventListener\Menu
tags: tags:
- { name: 'twig.extension' } - { name: kernel.event_listener, event: app.main_menu_configure, method: onMainMenuConfigure }
- { name: kernel.event_listener, event: app.admin_menu_configure, method: onAdminMenuConfigure }
app.twig.intl_extension:
public: false
class: Twig_Extensions_Extension_Intl
tags:
- { name: twig.extension }
# ================================================================================
# SECURITY
# ================================================================================
# security voter to check user-profile access
app.voter.user:
class: AppBundle\Voter\UserVoter
arguments: ["@security.access.decision_manager"]
tags:
- { name: security.voter }
# security voter to check customer access
timesheet.voter.customer:
class: TimesheetBundle\Voter\CustomerVoter
arguments: ["@security.access.decision_manager"]
tags:
- { name: security.voter }
# security voter to check project access
timesheet.voter.project:
class: TimesheetBundle\Voter\ProjectVoter
arguments: ["@security.access.decision_manager"]
tags:
- { name: security.voter }
# security voter to check activity access
timesheet.voter.activity:
class: TimesheetBundle\Voter\ActivityVoter
arguments: ["@security.access.decision_manager"]
tags:
- { name: security.voter }
# security voter to check activity access
timesheet.voter.timesheet:
class: TimesheetBundle\Voter\TimesheetVoter
arguments: ["@security.access.decision_manager"]
tags:
- { name: security.voter }
# ================================================================================
# FORMS
# ================================================================================
# form to edit user roles
app.admin.user_role:
class: AppBundle\Form\Type\UserRoleType
arguments: ["%security.role_hierarchy.roles%"]
tags:
- { name: form.type }
# event-listener to populate the navigation
app.menu_builder:
class: AppBundle\EventListener\MenuBuilder
arguments: ["@event_dispatcher", "@security.authorization_checker"]
tags:
- { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupNavbar }
# ================================================================================ # ================================================================================
# DATABASE # DATABASE
@@ -89,39 +52,83 @@ services:
# service that prefixes every database table # service that prefixes every database table
app.tableprefix_subscriber: app.tableprefix_subscriber:
class: AppBundle\Doctrine\TablePrefixSubscriber class: App\Doctrine\TablePrefixSubscriber
arguments: ["%database_prefix%"] arguments: ["%env(resolve:DATABASE_PREFIX)%"]
tags: tags:
- { name: doctrine.event_subscriber } - { name: doctrine.event_subscriber }
# updates timesheet records, to make sure they are calculated and can't be manipulated by the users
app.database_listener.timesheet: app.database_listener.timesheet:
class: TimesheetBundle\EventListener\TimesheetListener class: App\EventListener\TimesheetListener
tags: tags:
- { name: doctrine.event_listener, event: prePersist, lazy: true } - { name: doctrine.event_listener, event: prePersist, lazy: true }
- { name: doctrine.event_listener, event: preUpdate, lazy: true } - { name: doctrine.event_listener, event: preUpdate, lazy: true }
# Uncomment the following lines to define a service for the Post Doctrine repository. # Uncomment the following lines to define a service for the Timesheet Doctrine repository.
# It's not mandatory to create these services, but if you use repositories a lot, # It's not mandatory to create these services, but if you use repositories a lot,
# these services simplify your code: # these services can simplify your code:
# #
# app.post_repository: # app.post_repository:
# class: Doctrine\ORM\EntityRepository # class: Doctrine\ORM\EntityRepository
# factory: ['@doctrine.orm.entity_manager', getRepository] # factory: ['@doctrine.orm.entity_manager', getRepository]
# arguments: [AppBundle\Entity\User] # arguments: [App\Entity\Timesheet]
# #
# // traditional code inside a controller # // traditional code inside a controller
# $entityManager = $this->getDoctrine()->getManager(); # $entityManager = $this->getDoctrine()->getManager();
# $posts = $entityManager->getRepository('AppBundle:User')->findAll(); # $posts = $entityManager->getRepository('KimaiBundle:User')->findAll();
# #
# // same code using repository services # // same code using repository services
# $posts = $this->get('app.user_repository')->findAll(); # $posts = $this->get('app.user_repository')->findAll();
# ================================================================================
# EVENTS and LISTENER / SUBSCRIBER
# ================================================================================
# event-listener to populate the navigation
app.menu_builder:
class: App\EventListener\MenuBuilder
arguments: ["@event_dispatcher", "@security.authorization_checker"]
tags:
- { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupNavbar }
# ================================================================================
# FORMS
# ================================================================================
# form to edit user roles
app.admin.user_role:
class: App\Form\Type\UserRoleType
arguments: ["%security.role_hierarchy.roles%"]
tags:
- { name: form.type }
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
App\Command\RunCodeSnifferCommand:
arguments:
$projectDirectory: "%kernel.project_dir%"
App\Command\RunUnitTestsCommand:
class: App\Command\RunUnitTestsCommand
arguments:
$projectDirectory: "%kernel.project_dir%"
App\Command\RunIntegrationTestsCommand:
class: App\Command\RunIntegrationTestsCommand
arguments:
$projectDirectory: "%kernel.project_dir%"
# ================================================================================ # ================================================================================
# THEME # THEME
# ================================================================================ # ================================================================================
App\Twig\Extensions:
arguments: ['%app_locales%']
avanzu_admin_theme.navbar_user_listener: avanzu_admin_theme.navbar_user_listener:
class: AppBundle\EventListener\NavbarShowUserListener class: App\EventListener\NavbarShowUserListener
arguments: ["@security.token_storage"] arguments: ["@security.token_storage"]
tags: tags:
- { name: kernel.event_listener, event: theme.navbar_user, method: onShowUser } - { name: kernel.event_listener, event: theme.navbar_user, method: onShowUser }
@@ -147,31 +154,3 @@ services:
# tags: # tags:
# - { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupMenu } # - { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupMenu }
# - { name: kernel.event_listener, event: theme.breadcrumb, method: onSetupMenu } # - { name: kernel.event_listener, event: theme.breadcrumb, method: onSetupMenu }
# ================================================================================
# APPLICATION CORE
# ================================================================================
# a route listener, that injects the locale through a URL directory
app.redirect_to_preferred_locale_listener:
class: AppBundle\EventListener\RedirectToPreferredLocaleListener
arguments: ['@router', '%app_locales%', '%locale%']
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
# additional menu entries for the timesheet bundle
timesheet.configure_menu_listener:
class: TimesheetBundle\EventListener\Menu
tags:
- { name: kernel.event_listener, event: app.main_menu_configure, method: onMainMenuConfigure }
- { name: kernel.event_listener, event: app.admin_menu_configure, method: onAdminMenuConfigure }
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
app.command.create_user:
class: AppBundle\Command\CreateUserCommand
arguments: ["@security.password_encoder", "@doctrine", "@validator"]
tags:
- { name: console.command, command: kimai:create-user }

View File

@@ -2,30 +2,37 @@
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html --> <!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.1/phpunit.xsd"
backupGlobals="false" backupGlobals="false"
colors="true" colors="true"
bootstrap="app/autoload.php" bootstrap="vendor/autoload.php"
> >
<php> <php>
<ini name="error_reporting" value="-1" /> <ini name="error_reporting" value="-1" />
<server name="KERNEL_DIR" value="app/" /> <env name="KERNEL_CLASS" value="App\Kernel" />
<env name="APP_ENV" value="test"/>
<env name="APP_DEBUG" value="1"/>
<env name="APP_SECRET" value="5a79a1c866efef9ca1800f971d689f3e"/>
<!-- define your env variables for the test env here -->
<!-- ###+ doctrine/doctrine-bundle ### -->
<env name="DATABASE_URL" value="sqlite:///var/data/kimai_test.sqlite"/>
<!-- ###- doctrine/doctrine-bundle ### -->
<!-- ###+ symfony/swiftmailer-bundle ### -->
<env name="MAILER_URL" value="null://localhost"/>
<!-- ###- symfony/swiftmailer-bundle ### -->
</php> </php>
<testsuites> <testsuites>
<testsuite name="Project Test Suite"> <testsuite name="Project Test Suite">
<directory>src/*Bundle/Tests</directory> <directory>tests/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <listeners>
<whitelist> <!-- it begins a database transaction before every testcase and rolls it back after
<directory>src</directory> the test finished, so tests can manipulate the database without affecting other tests -->
<exclude> <listener class="\DAMA\DoctrineTestBundle\PHPUnit\PHPUnitListener" />
<directory>src/*Bundle/Resources</directory> </listeners>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit> </phpunit>

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

39
public/index.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
use App\Kernel;
use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\Request;
require __DIR__.'/../vendor/autoload.php';
// The check is to ensure we don't use .env in production
if (!isset($_SERVER['APP_ENV'])) {
if (!class_exists(Dotenv::class)) {
throw new \RuntimeException('APP_ENV environment variable is not defined. You need to define environment variables for configuration or add "symfony/dotenv" as a Composer dependency to load variables from a .env file.');
}
(new Dotenv())->load(__DIR__.'/../.env');
}
$env = $_SERVER['APP_ENV'] ?? 'dev';
$debug = $_SERVER['APP_DEBUG'] ?? ('prod' !== $env);
if ($debug) {
umask(0000);
Debug::enable();
}
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
Request::setTrustedHosts(explode(',', $trustedHosts));
}
$kernel = new Kernel($env, $debug);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

View File

@@ -2,3 +2,4 @@
# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
User-agent: * User-agent: *
Disallow: /

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. * 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 Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface; use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace AppBundle\Command; namespace App\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -30,11 +30,11 @@ class RunCodeSnifferCommand extends Command
/** /**
* RunCodeSnifferCommand constructor. * RunCodeSnifferCommand constructor.
* @param $rootDir * @param $projectDirectory
*/ */
public function __construct($rootDir) public function __construct($projectDirectory)
{ {
$this->rootDir = realpath($rootDir . '/../'); $this->rootDir = realpath($projectDirectory);
parent::__construct(); parent::__construct();
} }
@@ -44,7 +44,7 @@ class RunCodeSnifferCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('kimai:dev:phpcs') ->setName('kimai:phpcs')
->setDescription('Run PHP_CodeSniffer to check for the projects coding style') ->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, '/src');
$this->executeCodeSniffer($io, '/tests'); $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. * file that was distributed with this source code.
*/ */
namespace AppBundle\Command; namespace App\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -29,7 +29,7 @@ class RunIntegrationTestsCommand extends RunUnitTestsCommand
protected function configure() protected function configure()
{ {
$this $this
->setName('kimai:dev:test-integration') ->setName('kimai:test-integration')
->setDescription('Run all integration tests') ->setDescription('Run all integration tests')
->setHelp('This command will execute all integration tests with the annotation "@group integration".') ->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. * file that was distributed with this source code.
*/ */
namespace AppBundle\Command; namespace App\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -31,11 +31,11 @@ class RunUnitTestsCommand extends Command
/** /**
* RunCodeSnifferCommand constructor. * 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(); parent::__construct();
} }
@@ -45,7 +45,7 @@ class RunUnitTestsCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('kimai:dev:test-unit') ->setName('kimai:test-unit')
->setDescription('Run all unit tests') ->setDescription('Run all unit tests')
->setHelp('This command will execute all unit tests. Skips all tests with "@group integration" annotation.') ->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); $io = new SymfonyStyle($input, $output);
$this->executeTests($io, '/tests/AppBundle'); $this->executeTests($io, '/tests');
$this->executeTests($io, '/tests/TimesheetBundle');
} }
/** /**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code. * 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 Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Controller\TimesheetControllerTrait; use App\Controller\TimesheetControllerTrait;
use TimesheetBundle\Entity\Customer; use App\Entity\Customer;
use TimesheetBundle\Entity\Timesheet; use App\Entity\Timesheet;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; 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. * Controller used for manage timesheet entries in the admin part of the site.
@@ -55,7 +55,7 @@ class TimesheetController extends AbstractController
/* @var $entries Pagerfanta */ /* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query); $entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:admin:timesheet.html.twig', [ return $this->render('admin/timesheet.html.twig', [
'entries' => $entries, 'entries' => $entries,
'page' => $page, 'page' => $page,
'query' => $query, 'query' => $query,
@@ -91,7 +91,7 @@ class TimesheetController extends AbstractController
*/ */
public function editAction(Timesheet $entry, Request $request) 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) 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. * file that was distributed with this source code.
*/ */
namespace AppBundle\Controller\Admin; namespace App\Controller\Admin;
use AppBundle\Controller\AbstractController; use App\Controller\AbstractController;
use AppBundle\Entity\User; use App\Entity\User;
use AppBundle\Form\Toolbar\UserToolbarForm; use App\Form\Toolbar\UserToolbarForm;
use AppBundle\Form\UserCreateType; use App\Form\UserCreateType;
use AppBundle\Repository\Query\UserQuery; use App\Repository\Query\UserQuery;
use Pagerfanta\Pagerfanta; use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
@@ -54,7 +54,7 @@ class UserController extends AbstractController
->setRole($userRole) ->setRole($userRole)
; ;
return $query ; return $query;
} }
/** /**

View File

@@ -9,13 +9,13 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace AppBundle\Controller; namespace App\Controller;
use AppBundle\Entity\User; use App\Entity\User;
use TimesheetBundle\Entity\Activity; use App\Entity\Activity;
use TimesheetBundle\Entity\Customer; use App\Entity\Customer;
use TimesheetBundle\Entity\Project; use App\Entity\Project;
use TimesheetBundle\Entity\Timesheet; use App\Entity\Timesheet;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
@@ -41,7 +41,7 @@ class DashboardController extends Controller
$userStats = $this->getDoctrine()->getRepository(User::class)->getGlobalStatistics(); $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 // shouldn't know about Timesheets
$timesheetRepo = $this->getDoctrine()->getRepository(Timesheet::class); $timesheetRepo = $this->getDoctrine()->getRepository(Timesheet::class);

View File

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

View File

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

View File

@@ -9,19 +9,19 @@
* file that was distributed with this source code. * 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 Pagerfanta\Pagerfanta;
use TimesheetBundle\Entity\Activity; use App\Entity\Activity;
use TimesheetBundle\Entity\Customer; use App\Entity\Customer;
use TimesheetBundle\Entity\Timesheet; use App\Entity\Timesheet;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Component\HttpFoundation\Request; 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. * Controller used to manage timesheet contents in the public part of the site.
@@ -50,7 +50,7 @@ class TimesheetController extends AbstractController
/* @var $entries Pagerfanta */ /* @var $entries Pagerfanta */
$entries = $this->getRepository()->findByQuery($query); $entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:timesheet:index.html.twig', [ return $this->render('timesheet/index.html.twig', [
'entries' => $entries, 'entries' => $entries,
'page' => $page, 'page' => $page,
'query' => $query, 'query' => $query,
@@ -69,7 +69,7 @@ class TimesheetController extends AbstractController
$activeEntries = $this->getRepository()->getActiveEntries($user); $activeEntries = $this->getRepository()->getActiveEntries($user);
return $this->render( return $this->render(
'TimesheetBundle:Navbar:active-entries.html.twig', 'navbar/active-entries.html.twig',
['entries' => $activeEntries] ['entries' => $activeEntries]
); );
} }
@@ -127,7 +127,7 @@ class TimesheetController extends AbstractController
*/ */
public function editAction(Timesheet $entry, Request $request) 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) 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. * file that was distributed with this source code.
*/ */
namespace TimesheetBundle\Controller; namespace App\Controller;
use TimesheetBundle\Entity\Activity; use App\Entity\Activity;
use TimesheetBundle\Entity\Customer; use App\Entity\Customer;
use TimesheetBundle\Entity\Project; use App\Entity\Project;
use TimesheetBundle\Entity\Timesheet; use App\Entity\Timesheet;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Form\Toolbar\TimesheetToolbarForm; use App\Form\Toolbar\TimesheetToolbarForm;
use TimesheetBundle\Repository\Query\TimesheetQuery; use App\Repository\Query\TimesheetQuery;
use TimesheetBundle\Repository\TimesheetRepository; use App\Repository\TimesheetRepository;
/** /**
* Helper functions for Timesheet controller * Helper functions for Timesheet controller

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,13 +1,13 @@
<?php <?php
namespace AppBundle\Entity; namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
/** /**
* UserPreference * 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 * @ORM\Entity
*/ */
class UserPreference class UserPreference

View File

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

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