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)
/app/cache/*
/app/logs/*
!app/cache/.gitkeep
!app/logs/.gitkeep
###> symfony/framework-bundle ###
.env
/public/bundles/
/vendor/
###< symfony/framework-bundle ###
# Email spool folder
/app/spool/*
###> symfony/web-server-bundle ###
.web-server-pid
###< symfony/web-server-bundle ###
# Cache, session files and logs (Symfony3)
/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
# ========== KIMAI ==========
/bin/*
!bin/console
!bin/symfony_requirements
/vendor/
# Assets and user uploads
/web/bundles/
/web/uploads/
/public/theme/
# Assets managed by Bower
/web/assets/vendor/
/var/data/*.sqlite
# PHPUnit
/app/phpunit.xml
/phpunit.xml
/var/cache/*
!var/cache/.gitkeep
# Build data
/build/
/var/log/*
!var/log/.gitkeep
# Composer PHAR
/composer.phar
# Backup entities generated with doctrine:generate:entities command
*/Entity/*~
/var/sessions/*
!var/sessions/.gitkeep
# ========== KIMAI ==========
# IDE
.idea/
# SQLite files
/app/data/timesheet.sqlite
###> phpunit/phpunit ###
/phpunit.xml
###< phpunit/phpunit ###
# generated install and setup files
/web/theme/
###> friendsofphp/php-cs-fixer ###
.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).
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/))
- [Doctrine](https://github.com/doctrine/)
- Bower
## Requirements
- PHP 7 or higher
- PHP 7.1 or higher
- 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)
@@ -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
```
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)
Lets boostrap your environment by executing this commands (which is only available in dev environment):
```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.
@@ -83,7 +82,7 @@ $ bin/console doctrine:schema:drop --force
$ 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

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
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;
// 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);
use Symfony\Component\Dotenv\Dotenv;
set_time_limit(0);
/**
* @var Composer\Autoload\ClassLoader $loader
*/
$loader = require __DIR__.'/../app/autoload.php';
require __DIR__.'/../vendor/autoload.php';
$input = new ArgvInput();
$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev');
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
if ($debug) {
Debug::enable();
if (!class_exists(Application::class)) {
throw new \RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
}
$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->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",
"type": "project",
"description": "Kimai Time Tracking reloaded",
"autoload": {
"psr-4": {
"": "src/",
"KimaiTest\\": "tests/"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"require": {
"php": ">=7.0.8",
"php": "^7.1.3",
"ext-pdo_sqlite": "*",
"doctrine/doctrine-bundle": "^1.6",
"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",
"avanzu/admin-theme-bundle": "dev-master",
"beberlei/DoctrineExtensions": "^1.0",
"symfony/web-server-bundle": "3.4",
"avanzu/admin-theme-bundle": "dev-master"
"dama/doctrine-test-bundle": "^4.0",
"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": {
"sensio/generator-bundle": "~3.0",
"symfony/phpunit-bridge": "^3.0",
"squizlabs/php_codesniffer": "3.*",
"phpunit/phpunit": "^6"
},
"scripts": {
"post-install-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"
],
"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"
]
"doctrine/doctrine-fixtures-bundle": "^3.0",
"friendsofphp/php-cs-fixer": "^2.10",
"phpunit/phpunit": "^6.5",
"squizlabs/php_codesniffer": "^3.2",
"symfony/debug-pack": "^1.0",
"symfony/dotenv": "^4.0",
"symfony/maker-bundle": "^1.0",
"symfony/phpunit-bridge": "^4.0",
"symfony/web-server-bundle": "^4.0"
},
"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": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"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"
}
"symfony": {
"id": "01C3FWRDJJEX9K6Y3A4XDFXPBR",
"allow-contrib": false
}
}
}

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:
encoders:
# Our user class and the algorithm we'll use to encode passwords
# http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
AppBundle\Entity\User: bcrypt
App\Entity\User: bcrypt
# https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-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:
entity: { class: AppBundle:User, property: username }
entity: { class: App\Entity\User, property: username }
# http://symfony.com/doc/current/book/security.html#firewalls-authentication
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
# does what it says
logout_on_user_change: true
@@ -53,3 +53,4 @@ security:
- { path: '^/(%app_locales%)$', role: IS_AUTHENTICATED_FULLY }
- { path: '^/(%app_locales%)/login', role: IS_AUTHENTICATED_ANONYMOUSLY }
- { 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:
# 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:
class: AppBundle\Utils\Markdown
app.twig.app_extension:
public: false
class: AppBundle\Twig\Extensions
arguments: ['@markdown', '%app_locales%']
# a route listener, that injects the locale through a URL directory
app.redirect_to_preferred_locale_listener:
class: App\EventListener\RedirectToPreferredLocaleListener
arguments: ['@router', '%app_locales%', '%locale%']
tags:
- { name: twig.extension }
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
# twig function: template_from_string()
app.twig.loader_extension:
class: Twig_Extension_StringLoader
# additional menu entries for the timesheet bundle
timesheet.configure_menu_listener:
class: App\EventListener\Menu
tags:
- { name: 'twig.extension' }
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 }
- { name: kernel.event_listener, event: app.main_menu_configure, method: onMainMenuConfigure }
- { name: kernel.event_listener, event: app.admin_menu_configure, method: onAdminMenuConfigure }
# ================================================================================
# DATABASE
@@ -89,39 +52,83 @@ services:
# service that prefixes every database table
app.tableprefix_subscriber:
class: AppBundle\Doctrine\TablePrefixSubscriber
arguments: ["%database_prefix%"]
class: App\Doctrine\TablePrefixSubscriber
arguments: ["%env(resolve:DATABASE_PREFIX)%"]
tags:
- { 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:
class: TimesheetBundle\EventListener\TimesheetListener
class: App\EventListener\TimesheetListener
tags:
- { name: doctrine.event_listener, event: prePersist, 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,
# these services simplify your code:
# these services can simplify your code:
#
# app.post_repository:
# class: Doctrine\ORM\EntityRepository
# factory: ['@doctrine.orm.entity_manager', getRepository]
# arguments: [AppBundle\Entity\User]
# arguments: [App\Entity\Timesheet]
#
# // traditional code inside a controller
# $entityManager = $this->getDoctrine()->getManager();
# $posts = $entityManager->getRepository('AppBundle:User')->findAll();
# $posts = $entityManager->getRepository('KimaiBundle:User')->findAll();
#
# // same code using repository services
# $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
# ================================================================================
App\Twig\Extensions:
arguments: ['%app_locales%']
avanzu_admin_theme.navbar_user_listener:
class: AppBundle\EventListener\NavbarShowUserListener
class: App\EventListener\NavbarShowUserListener
arguments: ["@security.token_storage"]
tags:
- { name: kernel.event_listener, event: theme.navbar_user, method: onShowUser }
@@ -147,31 +154,3 @@ services:
# tags:
# - { name: kernel.event_listener, event: theme.sidebar_setup_menu, 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 -->
<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"
colors="true"
bootstrap="app/autoload.php"
bootstrap="vendor/autoload.php"
>
<php>
<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>
<testsuites>
<testsuite name="Project Test Suite">
<directory>src/*Bundle/Tests</directory>
<directory>tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
<listeners>
<!-- it begins a database transaction before every testcase and rolls it back after
the test finished, so tests can manipulate the database without affecting other tests -->
<listener class="\DAMA\DoctrineTestBundle\PHPUnit\PHPUnitListener" />
</listeners>
</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
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.
*/
namespace AppBundle\Command;
namespace App\Command;
use AppBundle\Entity\User;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Console\Command\Command;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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