improved code styles #158 (#172)

* use php-cs-fixer instead of phpcodesniffer
* updated scrutinizer config
* adjusted code yules to all files
* updated CONTRIBUTING guidelines
This commit is contained in:
Kevin Papst
2018-06-22 21:09:10 +02:00
committed by GitHub
parent 773d27bb0e
commit cd7cbeae88
142 changed files with 775 additions and 467 deletions

View File

@@ -2,7 +2,141 @@
return PhpCsFixer\Config::create()
->setRules([
'@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
'encoding' => true,
'full_opening_tag' => true,
'blank_line_after_namespace' => true,
'braces' => true,
'class_definition' => true,
'elseif' => true,
'function_declaration' => true,
'indentation_type' => true,
'line_ending' => true,
'lowercase_constants' => true,
'lowercase_keywords' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'no_break_comment' => true,
'no_closing_tag' => true,
'no_spaces_after_function_name' => true,
'no_spaces_inside_parenthesis' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'single_blank_line_at_eof' => true,
'single_class_element_per_statement' => ['elements' => ['property']],
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'array_syntax' => [
'syntax' => 'short'
],
'binary_operator_spaces' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => [
'statements' => ['return'],
],
'cast_spaces' => true,
'class_attributes_separation' => ['elements' => ['method']],
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => true,
'function_typehint_space' => true,
'include' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'native_function_casing' => true,
'new_with_braces' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => ['tokens' => [
'curly_brace_block',
'extra',
'parenthesis_brace_block',
'square_brace_block',
'throw',
'use',
]],
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => ['use' => 'echo'],
'no_multiline_whitespace_around_double_arrow' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_around_offset' => true,
'no_trailing_comma_in_list_call' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_curly_braces' => true,
'no_unneeded_final_method' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'php_unit_fqcn_annotation' => true,
'phpdoc_align' => [
'align' => 'left',
'tags' => [
'method',
'param',
'property',
'return',
'throws',
'type',
'var',
],
],
'phpdoc_annotation_without_dot' => true,
'phpdoc_indent' => true,
'phpdoc_inline_tag' => true,
'phpdoc_no_access' => true,
'phpdoc_no_alias_tag' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_return_self_reference' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => false,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => false,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'protected_to_private' => true,
'return_type_declaration' => true,
'semicolon_after_instruction' => true,
'short_scalar_cast' => true,
'single_blank_line_before_namespace' => true,
'single_line_comment_style' => [
'comment_types' => ['hash'],
],
'single_quote' => true,
'space_after_semicolon' => [
'remove_in_empty_for_expressions' => true,
],
'standardize_increment' => true,
'standardize_not_equals' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline_array' => false,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'whitespace_after_comma_in_array' => true,
'yoda_style' => false,
'ternary_to_null_coalescing' => true,
'visibility_required' => ['elements' => [
'const',
'method',
'property',
]],
])
->setFinder(
PhpCsFixer\Finder::create()
->in([
__DIR__ . '/src/',
__DIR__ . '/tests/',
])
)
->setFormat('checkstyle')
;

View File

@@ -3,17 +3,11 @@ build:
node: v8.11.2
nodes:
analysis:
project_setup:
override:
- 'true'
tests:
override:
- php-scrutinizer-run
-
command: phpcs-run
use_website_config: true
- js-scrutinizer-run
tests: true
- php-scrutinizer-run
tests:
tests:
override:
-
@@ -26,21 +20,21 @@ build:
coverage:
file: 'integration'
format: 'clover'
-
command: 'bin/console kimai:phpcs --checkstyle=checkstyle'
analysis:
file: 'checkstyle'
format: 'php-cs-checkstyle'
filter:
excluded_paths:
- 'tests/*'
- 'bin/*'
- '*/build/*'
- 'node_modules/*'
- 'public/*'
- 'var/*'
- 'vendor/*'
checks:
php: true
javascript: true
coding_style:
php:
spaces:
around_operators:
concatenation: true
- '.github/'
- 'bin/'
- 'config/'
- 'public/'
- 'templates/'
- 'translations/'
- 'var/'
dependency_paths:
- 'node_modules/'
- 'vendor/'

View File

@@ -6,11 +6,11 @@ Send us your ideas, code reviews, pull requests and feature requests to help us
## Pull request rules
- We use PSR-2 code styles, please run `bin/console kimai:phpcs` before sending in a pull-request
- Please add PHPUnit tests for your changes
- Verify everything still works by executing our tests `bin/console kimai:test-unit` and `bin/console kimai:test-integration`
- If you want to contribute new files, please add them with the file-header template from below
- We use PSR-2 with some addons code styles (check our [php-cs-fixer config](.php_cs.dist)), run `bin/console kimai:phpcs` to verify and `bin/console kimai:phpcs --fix` to fix violations
- Add PHPUnit tests for your changes, verify everything still works and execute our test-suites `bin/console kimai:test-unit` and `bin/console kimai:test-integration`
- If you contribute new files, please add them with the file-header template from below
- With sending in a PR, you accept that your contributions/code will be published under MIT license (see the LICENSE file as well)
- If one of the checks fail, please fix them before asking for a review
### File-header template
```
@@ -21,3 +21,27 @@ Send us your ideas, code reviews, pull requests and feature requests to help us
* file that was distributed with this source code.
*/
```
## Translations
We try to keep the number of language files small to make it easier to identify the location for your new messages.
- If you add a new key, you have to add it in every language file
- Its very likely that you want to edit the file `messages` as it holds 90% of our application translations
The files in a quick overview:
- `AvanzuAdminTheme` is only meant for translating strings from the original theme
- `exceptions` only holds translations of error pages and exception handlers
- `flashmessages`
- `messages` holds most of the visible application translations
- `pagerfanta` includes the translations for the pagination component
- `sidebar` holds all the translations of the right sidebar
- `validators` only hold translations related to violations/validation of submitted form data (or API calls)
## Documentation
The documentation is in [var/docs/](var/docs/) and its available both at GitHub and in your running Kimai instance.
- Please verify that all links work in your Kimai instance before submitting

View File

@@ -59,7 +59,7 @@ class CreateUserCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{
@@ -74,7 +74,7 @@ class CreateUserCommand extends Command
->addArgument(
'role',
InputArgument::OPTIONAL,
'A comma separated list of user roles, e.g. "'.$roles.'"',
'A comma separated list of user roles, e.g. "' . $roles . '"',
User::DEFAULT_ROLE
)
->addArgument('password', InputArgument::OPTIONAL, 'Password for the new user (requested if not provided)')
@@ -82,7 +82,7 @@ class CreateUserCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -92,7 +92,7 @@ class CreateUserCommand extends Command
$email = $input->getArgument('email');
$role = $input->getArgument('role');
if ($input->getArgument('password') !== null) {
if (null !== $input->getArgument('password')) {
$password = $input->getArgument('password');
} else {
$password = $this->askForPassword($input, $output);
@@ -122,6 +122,7 @@ class CreateUserCommand extends Command
. $error->getMessage()
);
}
return;
}

View File

@@ -35,10 +35,9 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
*/
class KimaiImporterCommand extends Command
{
// minimum required Kimai and database version, lower versions are not supported by this command
const MIN_VERSION = '1.0.1';
const MIN_REVISION = '1388';
public const MIN_VERSION = '1.0.1';
public const MIN_REVISION = '1388';
/**
* Create the user default passwords
@@ -110,7 +109,7 @@ class KimaiImporterCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{
@@ -130,7 +129,7 @@ class KimaiImporterCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -147,12 +146,14 @@ class KimaiImporterCommand extends Command
$password = $input->getArgument('password');
if (trim(strlen($password)) < 6) {
$io->error('Password length is not sufficient, at least 6 character are required');
return;
}
$country = $input->getArgument('country');
if (trim(strlen($country)) != 2) {
if (2 != trim(strlen($country))) {
$io->error('Country length needs to be exactly 2 character');
return;
}
@@ -174,6 +175,7 @@ class KimaiImporterCommand extends Command
$users = $this->fetchAllFromImport('users');
} catch (\Exception $ex) {
$io->error('Failed to load users: ' . $ex->getMessage());
return;
}
@@ -181,6 +183,7 @@ class KimaiImporterCommand extends Command
$customer = $this->fetchAllFromImport('customers');
} catch (\Exception $ex) {
$io->error('Failed to load customers: ' . $ex->getMessage());
return;
}
@@ -188,6 +191,7 @@ class KimaiImporterCommand extends Command
$projects = $this->fetchAllFromImport('projects');
} catch (\Exception $ex) {
$io->error('Failed to load projects: ' . $ex->getMessage());
return;
}
@@ -195,6 +199,7 @@ class KimaiImporterCommand extends Command
$activities = $this->fetchAllFromImport('activities');
} catch (\Exception $ex) {
$io->error('Failed to load activities: ' . $ex->getMessage());
return;
}
@@ -202,6 +207,7 @@ class KimaiImporterCommand extends Command
$activityToProject = $this->fetchAllFromImport('projects_activities');
} catch (\Exception $ex) {
$io->error('Failed to load activities-project mapping: ' . $ex->getMessage());
return;
}
@@ -209,6 +215,7 @@ class KimaiImporterCommand extends Command
$records = $this->fetchAllFromImport('timeSheet');
} catch (\Exception $ex) {
$io->error('Failed to load timeSheet: ' . $ex->getMessage());
return;
}
@@ -224,6 +231,7 @@ class KimaiImporterCommand extends Command
$io->success('Imported users: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import users: ' . $ex->getMessage());
return;
}
@@ -233,6 +241,7 @@ class KimaiImporterCommand extends Command
$io->success('Imported customers: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import customers: ' . $ex->getMessage());
return;
}
@@ -242,6 +251,7 @@ class KimaiImporterCommand extends Command
$io->success('Imported projects: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import projects: ' . $ex->getMessage());
return;
}
@@ -251,6 +261,7 @@ class KimaiImporterCommand extends Command
$io->success('Imported activities: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import activities: ' . $ex->getMessage());
return;
}
@@ -260,6 +271,7 @@ class KimaiImporterCommand extends Command
$io->success('Imported timesheet records: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import timesheet records: ' . $ex->getMessage());
return;
}
@@ -276,7 +288,7 @@ class KimaiImporterCommand extends Command
'Start: ' . $this->bytesHumanReadable($bytesStart) . PHP_EOL .
'After caching: ' . $this->bytesHumanReadable($bytesCached) . PHP_EOL .
'After import: ' . $this->bytesHumanReadable($bytesImported) . PHP_EOL .
'Total consumption for importing '.$allImports.' new database entries: ' .
'Total consumption for importing ' . $allImports . ' new database entries: ' .
$this->bytesHumanReadable($bytesImported - $bytesStart)
);
}
@@ -299,19 +311,21 @@ class KimaiImporterCommand extends Command
$version = $this->getImportConnection()->query($versionQuery)->fetchColumn();
$revision = $this->getImportConnection()->query($revisionQuery)->fetchColumn();
if (version_compare($requiredVersion, $version) == 1) {
if (1 == version_compare($requiredVersion, $version)) {
$io->error(
'Import can only performed from an up-to-date Kimai version:' . PHP_EOL .
'Needs at least ' . $requiredVersion . ' but found ' . $version
);
return false;
}
if (version_compare($requiredRevision, $revision) == 1) {
if (1 == version_compare($requiredRevision, $revision)) {
$io->error(
'Import can only performed from an up-to-date Kimai version:' . PHP_EOL .
'Database revision needs to be ' . $requiredRevision . ' but found ' . $revision
);
return false;
}
@@ -329,7 +343,7 @@ class KimaiImporterCommand extends Command
foreach ($allListener as $name => $listener) {
if (in_array($name, ['prePersist', 'preUpdate'])) {
foreach ($listener as $service => $class) {
if ($class === TimesheetSubscriber::class) {
if (TimesheetSubscriber::class === $class) {
$connection->getEventManager()->removeEventListener(['prePersist', 'preUpdate'], $class);
}
}
@@ -345,6 +359,7 @@ class KimaiImporterCommand extends Command
protected function bytesHumanReadable($size)
{
$unit = ['b', 'kB', 'MB', 'GB'];
return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
}
@@ -389,11 +404,12 @@ class KimaiImporterCommand extends Command
$value = $error->getInvalidValue();
$io->error(
$error->getPropertyPath()
. " (" . (is_array($value) ? implode(',', $value) : $value) .")"
. ' (' . (is_array($value) ? implode(',', $value) : $value) . ')'
. "\n "
. $error->getMessage()
);
}
return false;
}
@@ -435,8 +451,8 @@ class KimaiImporterCommand extends Command
$entityManager = $this->getDoctrine()->getManager();
foreach ($users as $oldUser) {
$isActive = (bool)$oldUser['active'] && !(bool)$oldUser['trash'] && !(bool)$oldUser['ban'];
$role = ($oldUser['globalRoleID'] == 1) ? User::ROLE_SUPER_ADMIN : User::DEFAULT_ROLE;
$isActive = (bool) $oldUser['active'] && !(bool) $oldUser['trash'] && !(bool) $oldUser['ban'];
$role = (1 == $oldUser['globalRoleID']) ? User::ROLE_SUPER_ADMIN : User::DEFAULT_ROLE;
$user = new User();
$user->setUsername($oldUser['name'])
@@ -460,7 +476,7 @@ class KimaiImporterCommand extends Command
if ($this->debug) {
$io->success('Created user: ' . $user->getUsername());
}
$counter++;
++$counter;
} catch (\Exception $ex) {
$io->error('Failed to create user: ' . $user->getUsername());
$io->error('Reason: ' . $ex->getMessage());
@@ -468,6 +484,7 @@ class KimaiImporterCommand extends Command
$this->users[$oldUser['userID']] = $user;
}
return $counter;
}
@@ -508,7 +525,7 @@ class KimaiImporterCommand extends Command
$entityManager = $this->getDoctrine()->getManager();
foreach ($customers as $oldCustomer) {
$isActive = (bool)$oldCustomer['visible'] && !(bool)$oldCustomer['trash'];
$isActive = (bool) $oldCustomer['visible'] && !(bool) $oldCustomer['trash'];
$name = $oldCustomer['name'];
if (empty($name)) {
$name = uniqid();
@@ -540,7 +557,7 @@ class KimaiImporterCommand extends Command
if ($this->debug) {
$io->success('Created customer: ' . $customer->getName());
}
$counter++;
++$counter;
} catch (\Exception $ex) {
$io->error('Reason: ' . $ex->getMessage());
$io->error('Failed to create customer: ' . $customer->getName());
@@ -548,6 +565,7 @@ class KimaiImporterCommand extends Command
$this->customers[$oldCustomer['customerID']] = $customer;
}
return $counter;
}
@@ -577,7 +595,7 @@ class KimaiImporterCommand extends Command
$entityManager = $this->getDoctrine()->getManager();
foreach ($projects as $oldProject) {
$isActive = (bool)$oldProject['visible'] && !(bool)$oldProject['trash'];
$isActive = (bool) $oldProject['visible'] && !(bool) $oldProject['trash'];
$customer = $this->customers[$oldProject['customerID']];
$name = $oldProject['name'];
if (empty($name)) {
@@ -603,7 +621,7 @@ class KimaiImporterCommand extends Command
if ($this->debug) {
$io->success('Created project: ' . $project->getName() . ' for customer: ' . $customer->getName());
}
$counter++;
++$counter;
} catch (\Exception $ex) {
$io->error('Failed to create project: ' . $project->getName());
$io->error('Reason: ' . $ex->getMessage());
@@ -611,6 +629,7 @@ class KimaiImporterCommand extends Command
$this->projects[$oldProject['projectID']] = $project;
}
return $counter;
}
@@ -662,11 +681,12 @@ class KimaiImporterCommand extends Command
$this->unassignedActivities[$oldActivity['activityID']] = $oldActivity;
$this->createActivity($io, $entityManager, $project, $oldActivity);
$counter++;
++$counter;
} else {
$this->unassignedActivities[$oldActivity['activityID']] = $oldActivity;
}
}
return $counter;
}
@@ -689,7 +709,7 @@ class KimaiImporterCommand extends Command
return $this->activities[$activityId][$project->getId()];
}
$isActive = (bool)$oldActivity['visible'] && !(bool)$oldActivity['trash'];
$isActive = (bool) $oldActivity['visible'] && !(bool) $oldActivity['trash'];
$name = $oldActivity['name'];
if (empty($name)) {
$name = uniqid();
@@ -778,13 +798,13 @@ class KimaiImporterCommand extends Command
$activity = $this->activities[$activityId][$projectId];
}
if ($activity === null && isset($this->unassignedActivities[$activityId])) {
if (null === $activity && isset($this->unassignedActivities[$activityId])) {
$oldActivity = $this->unassignedActivities[$activityId];
$activity = $this->createActivity($io, $entityManager, $project, $oldActivity);
$activityCounter++;
++$activityCounter;
}
if ($activity === null) {
if (null === $activity) {
$io->error('Could not create timesheet record, missing activity with ID: ' . $activityId);
continue;
}
@@ -792,7 +812,7 @@ class KimaiImporterCommand extends Command
$duration = $oldRecord['end'] - $oldRecord['start'];
$rate = $oldRecord['fixedRate'];
if ((empty($rate) || $rate == 0.00) && !empty($oldRecord['rate'])) {
if ((empty($rate) || 0.00 == $rate) && !empty($oldRecord['rate'])) {
$hourlyRate = (float) $oldRecord['rate'];
$rate = (float) $hourlyRate * ($duration / 3600);
$rate = round($rate, 2);
@@ -802,8 +822,8 @@ class KimaiImporterCommand extends Command
$timesheet
->setDescription($oldRecord['description'] ?: ($oldRecord['comment'] ?: null))
->setUser($this->users[$oldRecord['userID']])
->setBegin(new \DateTime("@".$oldRecord['start']))
->setEnd(new \DateTime("@".$oldRecord['end']))
->setBegin(new \DateTime('@' . $oldRecord['start']))
->setEnd(new \DateTime('@' . $oldRecord['end']))
->setDuration($duration)
->setActivity($activity)
->setRate($rate)
@@ -819,13 +839,13 @@ class KimaiImporterCommand extends Command
if ($this->debug) {
$io->success('Created timesheet record: ' . $timesheet->getId());
}
$counter++;
++$counter;
} catch (\Exception $ex) {
$io->error('Failed to create timesheet record: ' . $timesheet->getId());
$io->error('Reason: ' . $ex->getMessage());
}
if ($counter % 500 == 0) {
if (0 == $counter % 500) {
$io->writeln('Imported ' . $counter . ' timesheet records, import ongoing ...');
}
}
@@ -833,6 +853,7 @@ class KimaiImporterCommand extends Command
if ($activityCounter > 0) {
$io->success('Created new (previously unattached) activities during timesheet import: ' . $activityCounter);
}
return $counter;
}
}

View File

@@ -22,9 +22,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
*/
class ResetCommand extends Command
{
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{
@@ -56,6 +55,7 @@ EOT
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database: ' . $ex->getMessage());
return 1;
}
}
@@ -66,6 +66,7 @@ EOT
$command->run(new ArrayInput(['--force' => true]), $output);
} catch (\Exception $ex) {
$io->error('Failed to drop database schema: ' . $ex->getMessage());
return 2;
}
@@ -74,6 +75,7 @@ EOT
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to create database schema: ' . $ex->getMessage());
return 3;
}
}
@@ -85,6 +87,7 @@ EOT
$command->run($cmdInput, $output);
} catch (\Exception $ex) {
$io->error('Failed to import fixtures: ' . $ex->getMessage());
return 4;
}
@@ -94,6 +97,7 @@ EOT
$command->run(new ArrayInput([]), $output);
} catch (\Exception $ex) {
$io->error('Failed to clear cache: ' . $ex->getMessage());
return 5;
}
}
@@ -101,7 +105,6 @@ EOT
return 0;
}
/**
* @param InputInterface $input
* @param OutputInterface $output

View File

@@ -11,22 +11,22 @@ namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Command used to check the project coding styles.
* Command used to check and apply the projects coding styles.
*/
class RunCodeSnifferCommand extends Command
{
/**
* @var string
*/
protected $rootDir;
protected $rootDir = '';
/**
* RunCodeSnifferCommand constructor.
* @param $projectDirectory
* @param string $projectDirectory
*/
public function __construct($projectDirectory)
{
@@ -35,46 +35,64 @@ class RunCodeSnifferCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('kimai:phpcs')
->setDescription('Run PHP_CodeSniffer to check for the projects coding style')
->addOption('fix', null, InputOption::VALUE_NONE, 'Fix all found problems (risky: modifies your files)')
->addOption('checkstyle', null, InputOption::VALUE_OPTIONAL, '')
;
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$this->executeCodeSniffer($io, '/src');
$this->executeCodeSniffer($io, '/tests');
$this->executeCodeSniffer($io, '/templates');
$filename = null;
ob_start();
$args = [];
if (!$input->getOption('fix')) {
$filename = $input->getOption('checkstyle');
$args[] = '--dry-run';
$args[] = '--verbose';
$args[] = '--show-progress=none';
if (!empty($filename) && (file_exists($filename) && !is_writeable($filename))) {
$io->error('Target file is not writeable: ' . $filename);
return;
}
/**
* @param string $directory
*/
protected function executeCodeSniffer(SymfonyStyle $io, $directory)
{
$directory = $this->rootDir . $directory;
if (!empty($filename)) {
$filename = $this->rootDir . '/' . $filename;
$args[] = '> ' . $filename;
} else {
$args[] = '--format=txt';
}
}
$exitCode = 0;
ob_start();
passthru($this->rootDir . '/bin/phpcs --standard=PSR2 ' . $directory, $exitCode);
passthru($this->rootDir . '/vendor/bin/php-cs-fixer fix ' . implode(' ', $args), $exitCode);
$result = ob_get_clean();
$io->write($result);
if ($exitCode > 0) {
$io->error('Found problems while checking sources at: ' . $directory);
} else {
$io->success('All sources look good at: ' . $directory);
$io->error(
'Found problems while checking your code styles' .
(!empty($filename) ? '. Saved checkstyle data to: ' . $filename : '')
);
return;
}
$io->success('All source files have proper code styles');
}
}

View File

@@ -10,9 +10,6 @@
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Command used to run all integration tests.
@@ -20,7 +17,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
class RunIntegrationTestsCommand extends RunUnitTestsCommand
{
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{

View File

@@ -19,7 +19,6 @@ use Symfony\Component\Console\Style\SymfonyStyle;
*/
class RunUnitTestsCommand extends Command
{
/**
* @var string
*/
@@ -36,7 +35,7 @@ class RunUnitTestsCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function configure()
{
@@ -48,7 +47,7 @@ class RunUnitTestsCommand extends Command
}
/**
* @inheritdoc
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{

View File

@@ -17,9 +17,9 @@ class Constants
/**
* Currently only used for informational purpose in the footer
*/
const VERSION = '2.0 dev';
public const VERSION = '2.0 dev';
/**
* Used in multiple views
*/
const GITHUB = 'https://github.com/kevinpapst/kimai2/';
public const GITHUB = 'https://github.com/kevinpapst/kimai2/';
}

View File

@@ -17,14 +17,14 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
*/
abstract class AbstractController extends Controller
{
const FLASH_SUCCESS = 'success';
const FLASH_WARNING = 'warning';
const FLASH_ERROR = 'error';
public const FLASH_SUCCESS = 'success';
public const FLASH_WARNING = 'warning';
public const FLASH_ERROR = 'error';
const DOMAIN_FLASH = 'flashmessages';
const DOMAIN_ERROR = 'exceptions';
public const DOMAIN_FLASH = 'flashmessages';
public const DOMAIN_ERROR = 'exceptions';
const ROLE_ADMIN = 'ROLE_ADMIN';
public const ROLE_ADMIN = 'ROLE_ADMIN';
/**
* @return object|\Symfony\Component\Translation\DataCollectorTranslator|\Symfony\Component\Translation\IdentityTranslator
@@ -37,8 +37,8 @@ abstract class AbstractController extends Controller
/**
* A translated helper for denyAccessUnlessGranted()
*
* @param $attributes
* @param null $subject
* @param mixed $attributes
* @param mixed $subject
* @param string $translation
* @param array $parameter
* @throws AccessDeniedException

View File

@@ -10,7 +10,6 @@
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use App\Entity\Activity;
use App\Repository\ActivityRepository;
@@ -22,7 +21,6 @@ use App\Repository\ActivityRepository;
*/
class ActivityController extends Controller
{
/**
* @return ActivityRepository
*/

View File

@@ -30,7 +30,6 @@ use App\Repository\Query\ActivityQuery;
*/
class ActivityController extends AbstractController
{
/**
* @return \App\Repository\ActivityRepository
*/
@@ -116,7 +115,7 @@ class ActivityController extends AbstractController
$deleteForm->handleRequest($request);
if ($stats->getRecordAmount() == 0 || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
if (0 == $stats->getRecordAmount() || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($activity);
$entityManager->flush();

View File

@@ -29,7 +29,6 @@ use App\Repository\Query\CustomerQuery;
*/
class CustomerController extends AbstractController
{
/**
* @return \App\Repository\CustomerRepository
*/
@@ -133,7 +132,7 @@ class CustomerController extends AbstractController
$deleteForm->handleRequest($request);
if ($stats->getRecordAmount() == 0 || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
if (0 == $stats->getRecordAmount() || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($customer);
$entityManager->flush();

View File

@@ -31,7 +31,6 @@ use App\Repository\Query\ProjectQuery;
*/
class ProjectController extends AbstractController
{
/**
* @return \App\Repository\ProjectRepository
*/
@@ -110,7 +109,7 @@ class ProjectController extends AbstractController
$deleteForm->handleRequest($request);
if ($stats->getRecordAmount() == 0 || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
if (0 == $stats->getRecordAmount() || ($deleteForm->isSubmitted() && $deleteForm->isValid())) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($project);
$entityManager->flush();

View File

@@ -133,10 +133,16 @@ class TimesheetController extends AbstractController
*/
public function deleteAction(Timesheet $entry, Request $request)
{
try {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($entry);
$entityManager->flush();
$this->flashSuccess('action.deleted_successfully');
} catch (\Exception $ex) {
$this->flashError('action.deleted.error', ['%reason%' => $ex->getMessage()]);
}
return $this->redirectToRoute('admin_timesheet_paginated', ['page' => $request->get('page')]);
}

View File

@@ -29,7 +29,6 @@ use Symfony\Component\HttpFoundation\Request;
*/
class UserController extends AbstractController
{
/**
* @Route("/", defaults={"page": 1}, name="admin_user")
* @Route("/page/{page}", requirements={"page": "[1-9]\d*"}, name="admin_user_paginated")

View File

@@ -105,7 +105,7 @@ class DashboardController extends Controller
//"{{ widgets.info_box_counter('stats.amountThisMonth', timesheetGlobal.amountThisMonth|money, 'money', 'green') }}",
"{{ widgets.info_box_counter('stats.durationTotal', timesheetGlobal.durationTotal|duration(true), 'hourglass-o', 'yellow') }}",
//"{{ widgets.info_box_counter('stats.amountTotal', timesheetGlobal.amountTotal|money, 'money', 'red') }}",
"{{ widgets.info_box_counter('stats.activeRecordings', timesheetGlobal.activeCurrently, 'hourglass-o', 'red', path('admin_timesheet', {'state': ".TimesheetQuery::STATE_RUNNING."})) }}",
"{{ widgets.info_box_counter('stats.activeRecordings', timesheetGlobal.activeCurrently, 'hourglass-o', 'red', path('admin_timesheet', {'state': " . TimesheetQuery::STATE_RUNNING . '})) }}',
],
];

View File

@@ -23,9 +23,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
*/
class HelpController extends Controller
{
const README = 'README';
const DOCS_DIR = 'var/docs/';
public const README = 'README';
public const DOCS_DIR = 'var/docs/';
/**
* @var string
@@ -49,10 +48,10 @@ class HelpController extends Controller
* @param string $chapter
* @return \Symfony\Component\HttpFoundation\Response
*/
public function indexAction(?string $chapter)
public function indexAction(string $chapter)
{
$breadcrumb = [self::README];
if ($chapter !== self::README) {
if (self::README !== $chapter) {
$breadcrumb[] = $chapter;
}

View File

@@ -18,6 +18,7 @@ use App\Model\InvoiceModel;
use App\Repository\Query\BaseQuery;
use App\Repository\Query\InvoiceQuery;
use App\Repository\Query\TimesheetQuery;
use App\Repository\TimesheetRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
@@ -31,7 +32,6 @@ use Symfony\Component\HttpFoundation\Request;
*/
class InvoiceController extends AbstractController
{
/**
* @var ServiceInvoice
*/
@@ -97,11 +97,13 @@ class InvoiceController extends AbstractController
$query = $form->getData();
$query->setResultType(TimesheetQuery::RESULT_TYPE_QUERYBUILDER);
if ($query->getCustomer() !== null) {
if (null !== $query->getCustomer()) {
$query->getBegin()->setTime(0, 0, 0);
$query->getEnd()->setTime(23, 59, 59);
$queryBuilder = $this->getDoctrine()->getRepository(Timesheet::class)->findByQuery($query);
/* @var TimesheetRepository $timeRepo */
$timeRepo = $this->getDoctrine()->getRepository(Timesheet::class);
$queryBuilder = $timeRepo->findByQuery($query);
$entries = $queryBuilder->getQuery()->getResult();
}
}
@@ -114,12 +116,12 @@ class InvoiceController extends AbstractController
$action = null;
if ($query->getTemplate() !== null) {
$generator = $this->service->getNumberGeneratorByName($query->getTemplate()->getNumberGenerator());
if ($generator === null) {
if (null === $generator) {
throw new \Exception('Unknown number generator: ' . $query->getTemplate()->getNumberGenerator());
}
$calculator = $this->service->getCalculatorByName($query->getTemplate()->getCalculator());
if ($calculator === null) {
if (null === $calculator) {
throw new \Exception('Unknown invoice calculator: ' . $query->getTemplate()->getCalculator());
}
@@ -144,12 +146,12 @@ class InvoiceController extends AbstractController
* TODO permission
*
* @param $page
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listTemplateAction($page, Request $request)
public function listTemplateAction($page)
{
$templates = $this->getRepository()->findByQuery(new BaseQuery());
return $this->render('invoice/templates.html.twig', [
'entries' => $templates,
'page' => $page,
@@ -186,6 +188,7 @@ class InvoiceController extends AbstractController
if (!$this->getRepository()->hasTemplate()) {
$this->flashWarning('invoice.first_template');
}
return $this->renderTemplateForm(new InvoiceTemplate(), $request);
}

View File

@@ -9,7 +9,7 @@
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
@@ -18,7 +18,7 @@ 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 AbstractController
class SecurityController extends SymfonyAbstractController
{
/**
* @Route("/login", name="security_login")
@@ -30,6 +30,7 @@ class SecurityController extends AbstractController
'error' => $helper->getLastAuthenticationError(),
]);
}
/**
* This is the route the user can use to logout.
*

View File

@@ -95,10 +95,9 @@ class TimesheetController extends AbstractController
* @Security("is_granted('stop', entry)")
*
* @param Timesheet $entry
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function stopAction(Timesheet $entry, Request $request)
public function stopAction(Timesheet $entry)
{
return $this->stop($entry, 'timesheet');
}
@@ -110,10 +109,9 @@ class TimesheetController extends AbstractController
* @Method({"GET", "POST"})
* @Security("is_granted('start', activity)")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function startAction(Activity $activity, Request $request)
public function startAction(Activity $activity)
{
$user = $this->getUser();
@@ -170,10 +168,16 @@ class TimesheetController extends AbstractController
*/
public function deleteAction(Timesheet $entry, Request $request)
{
try {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($entry);
$entityManager->flush();
$this->flashSuccess('action.deleted_successfully');
} catch (\Exception $ex) {
$this->flashError('action.deleted.error', ['%reason%' => $ex->getMessage()]);
}
return $this->redirectToRoute('timesheet_paginated', ['page' => $request->get('page')]);
}

View File

@@ -10,15 +10,17 @@
namespace App\Controller;
use App\Entity\Timesheet;
use Symfony\Component\HttpFoundation\Request;
use App\Repository\TimesheetRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Helper functions for Timesheet controller
*/
trait TimesheetControllerTrait
{
/**
* @var bool
*/
@@ -164,4 +166,45 @@ trait TimesheetControllerTrait
* @return \Symfony\Component\Form\FormInterface
*/
abstract protected function getEditForm(Timesheet $entry, $page);
/**
* Adds a "successful" flash message to the stack.
*
* @param string $translationKey
* @param array $parameter
*/
abstract protected function flashSuccess($translationKey, $parameter = []);
/**
* Adds a "error" flash message to the stack.
*
* @param $translationKey
* @param array $parameter
*/
abstract protected function flashError($translationKey, $parameter = []);
/**
* Shortcut to return the Doctrine Registry service.
*
* @throws \LogicException If DoctrineBundle is not available
*/
abstract protected function getDoctrine(): ManagerRegistry;
/**
* Returns a RedirectResponse to the given route with the given parameters.
*/
abstract protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse;
/**
* Renders a view.
*/
abstract protected function render(string $view, array $parameters = [], Response $response = null): Response;
/**
* Get a user from the Security Token Storage.
*
* @return mixed
* @throws \LogicException If SecurityBundle is not available
*/
abstract protected function getUser();
}

View File

@@ -26,11 +26,11 @@ class AppFixtures extends Fixture
{
use FixturesTrait;
const DEFAULT_PASSWORD = 'kitten';
const USERNAME_USER = 'john_user';
const USERNAME_TEAMLEAD = 'tony_teamlead';
const USERNAME_ADMIN = 'anna_admin';
const USERNAME_SUPER_ADMIN = 'susan_super';
public const DEFAULT_PASSWORD = 'kitten';
public const USERNAME_USER = 'john_user';
public const USERNAME_TEAMLEAD = 'tony_teamlead';
public const USERNAME_ADMIN = 'anna_admin';
public const USERNAME_SUPER_ADMIN = 'susan_super';
/**
* @var UserPasswordEncoderInterface
@@ -87,7 +87,7 @@ class AppFixtures extends Fixture
}
/**
* @return []
* @return array
*/
protected function getUserDefinition()
{

View File

@@ -44,6 +44,7 @@ trait FixturesTrait
protected function getRandomPhrase()
{
$phrases = $this->getPhrases();
return $phrases[array_rand($phrases)];
}
}

View File

@@ -22,7 +22,6 @@ use Doctrine\Common\Persistence\ObjectManager;
*/
class InvoiceFixtures extends Fixture
{
/**
* {@inheritdoc}
*/

View File

@@ -28,9 +28,9 @@ class TimesheetFixtures extends Fixture
{
use FixturesTrait;
const AMOUNT_TIMESHEET = 5000; // timesheet entries total
const RATE_MIN = 10; // minimum rate for one hour
const RATE_MAX = 80; // maximum rate for one hour
public const AMOUNT_TIMESHEET = 5000; // timesheet entries total
public const RATE_MIN = 10; // minimum rate for one hour
public const RATE_MAX = 80; // maximum rate for one hour
/**
* {@inheritdoc}
@@ -55,6 +55,7 @@ class TimesheetFixtures extends Fixture
foreach ($entries as $temp) {
$all[$temp->getId()] = $temp;
}
return $all;
}
@@ -70,6 +71,7 @@ class TimesheetFixtures extends Fixture
foreach ($entries as $temp) {
$all[$temp->getId()] = $temp;
}
return $all;
}
@@ -85,8 +87,10 @@ class TimesheetFixtures extends Fixture
foreach ($entries as $temp) {
$all[$temp->getId()] = $temp;
}
return $all;
}
/**
* @param ObjectManager $manager
* @return Activity[]
@@ -99,6 +103,7 @@ class TimesheetFixtures extends Fixture
foreach ($entries as $temp) {
$all[$temp->getId()] = $temp;
}
return $all;
}
@@ -181,7 +186,7 @@ class TimesheetFixtures extends Fixture
$i = 1;
foreach ($allCustomer as $customerName) {
$visible = $i++ % 6 != 0;
$visible = 0 != $i++ % 6;
$entry = new Customer();
$entry
->setCurrency($this->getRandomCurrency())
@@ -205,7 +210,7 @@ class TimesheetFixtures extends Fixture
foreach ($allCustomer as $id => $customer) {
$projectForCustomer = rand(0, 7);
for ($i = 1; $i <= $projectForCustomer; $i++) {
$visible = $i % 5 != 0;
$visible = 0 != $i % 5;
$entry = new Project();
$entry
@@ -228,7 +233,7 @@ class TimesheetFixtures extends Fixture
foreach ($allProject as $projectId => $project) {
$activityCount = rand(0, 10);
for ($i = 1; $i <= $activityCount; $i++) {
$visible = $i % 4 != 0;
$visible = 0 != $i % 4;
$entry = new Activity();
$entry
->setName($this->getRandomActivity() . ($visible ? '' : '.'))
@@ -283,6 +288,7 @@ class TimesheetFixtures extends Fixture
private function getRandomActivity()
{
$all = $this->getActivities();
return $all[array_rand($all)];
}
@@ -321,6 +327,7 @@ class TimesheetFixtures extends Fixture
private function getRandomProject()
{
$all = $this->getProjects();
return $all[array_rand($all)];
}
@@ -361,6 +368,7 @@ class TimesheetFixtures extends Fixture
private function getRandomLocation()
{
$all = $this->getLocations();
return $all[array_rand($all)];
}
@@ -430,6 +438,7 @@ class TimesheetFixtures extends Fixture
private function getRandomCurrency()
{
$all = $this->getCurrencies();
return $all[array_rand($all)];
}
}

View File

@@ -18,7 +18,6 @@ use Symfony\Component\Yaml\Yaml;
*/
class DoctrineCompilerPass implements CompilerPassInterface
{
/**
* @var string[]
*/
@@ -47,16 +46,16 @@ class DoctrineCompilerPass implements CompilerPassInterface
}
*/
if ($engine === null) {
if (null === $engine) {
$dbConfig = explode('://', getenv('DATABASE_URL'));
$engine = $dbConfig['0'] ?: null;
}
if ($engine === null) {
if (null === $engine) {
$engine = getenv('DATABASE_ENGINE');
}
if ($engine === null) {
if (null === $engine) {
throw new \Exception(
'Could not detect database engine. Please set the environment config DATABASE_ENGINE ' .
'to one of: "' . implode(', ', $this->allowedEngines) . '" in your .env file: DATABASE_ENGINE=sqlite'

View File

@@ -40,7 +40,7 @@ class TablePrefixSubscriber implements EventSubscriber
$classMetadata->setPrimaryTable(['name' => $this->prefix . $classMetadata->getTableName()]);
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY
if (\Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY == $mapping['type']
// Check if "joinTable" exists:
// it can be null if this field is the reverse side of a ManyToMany relationship
&& array_key_exists('name', $classMetadata->associationMappings[$fieldName]['joinTable'])) {

View File

@@ -20,9 +20,8 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
class Activity
{
/**
* @var integer
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
@@ -56,7 +55,7 @@ class Activity
private $comment;
/**
* @var boolean
* @var bool
*
* @ORM\Column(name="visible", type="boolean", nullable=false)
* @Assert\NotNull()
@@ -85,6 +84,7 @@ class Activity
public function setProject($project)
{
$this->project = $project;
return $this;
}
@@ -97,6 +97,7 @@ class Activity
public function setName($name)
{
$this->name = $name;
return $this;
}
@@ -119,6 +120,7 @@ class Activity
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
@@ -135,20 +137,21 @@ class Activity
/**
* Set visible
*
* @param boolean $visible
* @param bool $visible
*
* @return Activity
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* @return boolean
* @return bool
*/
public function getVisible()
{
@@ -158,7 +161,7 @@ class Activity
/**
* Get activity id
*
* @return integer
* @return int
*/
public function getId()
{

View File

@@ -20,11 +20,10 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
class Customer
{
const DEFAULT_CURRENCY = 'EUR';
public const DEFAULT_CURRENCY = 'EUR';
/**
* @var integer
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
@@ -63,7 +62,7 @@ class Customer
private $projects;
/**
* @var boolean
* @var bool
*
* @ORM\Column(name="visible", type="boolean", nullable=false)
* @Assert\NotNull()
@@ -167,6 +166,7 @@ class Customer
public function setName($name)
{
$this->name = $name;
return $this;
}
@@ -187,6 +187,7 @@ class Customer
public function setNumber(string $number)
{
$this->number = $number;
return $this;
}
@@ -207,6 +208,7 @@ class Customer
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
@@ -223,19 +225,20 @@ class Customer
/**
* Set visible
*
* @param boolean $visible
* @param bool $visible
* @return Customer
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* @return boolean
* @return bool
*/
public function getVisible()
{
@@ -251,6 +254,7 @@ class Customer
public function setCompany($company)
{
$this->company = $company;
return $this;
}
@@ -273,6 +277,7 @@ class Customer
public function setContact($contact)
{
$this->contact = $contact;
return $this;
}
@@ -293,6 +298,7 @@ class Customer
public function setAddress($address)
{
$this->address = $address;
return $this;
}
@@ -313,6 +319,7 @@ class Customer
public function setCountry($country)
{
$this->country = $country;
return $this;
}
@@ -333,6 +340,7 @@ class Customer
public function setCurrency($currency)
{
$this->currency = $currency;
return $this;
}
@@ -353,6 +361,7 @@ class Customer
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
@@ -375,6 +384,7 @@ class Customer
public function setFax($fax)
{
$this->fax = $fax;
return $this;
}
@@ -397,6 +407,7 @@ class Customer
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
@@ -419,6 +430,7 @@ class Customer
public function setMail($mail)
{
$this->mail = $mail;
return $this;
}
@@ -441,6 +453,7 @@ class Customer
public function setHomepage($homepage)
{
$this->homepage = $homepage;
return $this;
}
@@ -463,6 +476,7 @@ class Customer
public function setTimezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
@@ -483,6 +497,7 @@ class Customer
public function setProjects($projects)
{
$this->projects = $projects;
return $this;
}

View File

@@ -26,7 +26,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class InvoiceTemplate
{
/**
* @var integer
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
@@ -128,6 +128,7 @@ class InvoiceTemplate
public function setName($name)
{
$this->name = $name;
return $this;
}
@@ -156,6 +157,7 @@ class InvoiceTemplate
public function setTitle(string $title)
{
$this->title = $title;
return $this;
}
@@ -174,6 +176,7 @@ class InvoiceTemplate
public function setAddress($address)
{
$this->address = $address;
return $this;
}
@@ -192,6 +195,7 @@ class InvoiceTemplate
public function setNumberGenerator(string $numberGenerator)
{
$this->numberGenerator = $numberGenerator;
return $this;
}
@@ -210,6 +214,7 @@ class InvoiceTemplate
public function setDueDays(int $dueDays)
{
$this->dueDays = $dueDays;
return $this;
}
@@ -228,6 +233,7 @@ class InvoiceTemplate
public function setVat(float $vat)
{
$this->vat = $vat;
return $this;
}
@@ -246,6 +252,7 @@ class InvoiceTemplate
public function setCompany(string $company)
{
$this->company = $company;
return $this;
}
@@ -264,6 +271,7 @@ class InvoiceTemplate
public function setRenderer(string $renderer)
{
$this->renderer = $renderer;
return $this;
}
@@ -282,6 +290,7 @@ class InvoiceTemplate
public function setCalculator(string $calculator)
{
$this->calculator = $calculator;
return $this;
}
@@ -300,6 +309,7 @@ class InvoiceTemplate
public function setPaymentTerms(string $paymentTerms)
{
$this->paymentTerms = $paymentTerms;
return $this;
}

View File

@@ -20,9 +20,8 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
class Project
{
/**
* @var integer
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
@@ -64,7 +63,7 @@ class Project
private $comment;
/**
* @var boolean
* @var bool
*
* @ORM\Column(name="visible", type="boolean", nullable=false)
* @Assert\NotNull()
@@ -89,7 +88,7 @@ class Project
/**
* Get projectid
*
* @return integer
* @return int
*/
public function getId()
{
@@ -111,6 +110,7 @@ class Project
public function setCustomer($customer)
{
$this->customer = $customer;
return $this;
}
@@ -123,6 +123,7 @@ class Project
public function setName($name)
{
$this->name = $name;
return $this;
}
@@ -145,6 +146,7 @@ class Project
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
@@ -161,19 +163,20 @@ class Project
/**
* Set visible
*
* @param boolean $visible
* @param bool $visible
* @return Project
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* @return boolean
* @return bool
*/
public function getVisible()
{
@@ -189,6 +192,7 @@ class Project
public function setBudget($budget)
{
$this->budget = $budget;
return $this;
}
@@ -209,6 +213,7 @@ class Project
public function setActivities($activities)
{
$this->activities = $activities;
return $this;
}
@@ -235,6 +240,7 @@ class Project
public function setOrderNumber($orderNumber)
{
$this->orderNumber = $orderNumber;
return $this;
}

View File

@@ -9,7 +9,6 @@
namespace App\Entity;
use App\Entity\User;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@@ -29,9 +28,8 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
*/
class Timesheet
{
/**
* @var integer
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
@@ -55,7 +53,7 @@ class Timesheet
private $end;
/**
* @var integer
* @var int
*
* @ORM\Column(name="duration", type="integer", nullable=true)
* @Assert\GreaterThanOrEqual(0)
@@ -97,7 +95,7 @@ class Timesheet
/**
* Get entry id
*
* @return integer
* @return int
*/
public function getId()
{
@@ -119,6 +117,7 @@ class Timesheet
public function setBegin($begin)
{
$this->begin = $begin;
return $this;
}
@@ -137,7 +136,7 @@ class Timesheet
public function setEnd($end)
{
$this->end = $end;
if ($end === null) {
if (null === $end) {
$this->duration = 0;
}
@@ -147,12 +146,13 @@ class Timesheet
/**
* Set duration
*
* @param integer $duration
* @param int $duration
* @return Timesheet
*/
public function setDuration($duration)
{
$this->duration = $duration;
return $this;
}
@@ -160,7 +160,7 @@ class Timesheet
* Get duration
* Do not rely on the results of this method for active records.
*
* @return integer
* @return int
*/
public function getDuration()
{
@@ -176,6 +176,7 @@ class Timesheet
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
@@ -198,6 +199,7 @@ class Timesheet
public function setActivity($activity)
{
$this->activity = $activity;
return $this;
}
@@ -220,6 +222,7 @@ class Timesheet
public function setDescription($description)
{
$this->description = $description;
return $this;
}
@@ -242,6 +245,7 @@ class Timesheet
public function setRate($rate)
{
$this->rate = $rate;
return $this;
}
@@ -263,7 +267,7 @@ class Timesheet
*/
public function validate(ExecutionContextInterface $context, $payload)
{
if ($this->getEnd() !== null && $this->getEnd()->getTimestamp() < $this->getBegin()->getTimestamp()) {
if (null !== $this->getEnd() && $this->getEnd()->getTimestamp() < $this->getBegin()->getTimestamp()) {
$context->buildViolation('End date must not be earlier then start date.')
->atPath('end')
->setTranslationDomain('validators')

View File

@@ -6,7 +6,6 @@ use App\Validator\Constraints as KimaiAssert;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
@@ -27,12 +26,12 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
*/
class User implements UserInterface
{
const ROLE_CUSTOMER = 'ROLE_CUSTOMER';
const ROLE_USER = 'ROLE_USER';
const ROLE_TEAMLEAD = 'ROLE_TEAMLEAD';
const ROLE_ADMIN = 'ROLE_ADMIN';
const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
const DEFAULT_ROLE = self::ROLE_USER;
public const ROLE_CUSTOMER = 'ROLE_CUSTOMER';
public const ROLE_USER = 'ROLE_USER';
public const ROLE_TEAMLEAD = 'ROLE_TEAMLEAD';
public const ROLE_ADMIN = 'ROLE_ADMIN';
public const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const DEFAULT_ROLE = self::ROLE_USER;
/**
* @var int
@@ -85,7 +84,7 @@ class User implements UserInterface
private $alias;
/**
* @var boolean
* @var bool
*
* @ORM\Column(name="active", type="boolean", nullable=false)
* @Assert\NotNull()
@@ -184,7 +183,7 @@ class User implements UserInterface
}
/**
* @param boolean $active
* @param bool $active
* @return $this
*/
public function setActive($active)
@@ -195,7 +194,7 @@ class User implements UserInterface
}
/**
* @return boolean
* @return bool
*/
public function isActive()
{
@@ -242,6 +241,7 @@ class User implements UserInterface
public function setPlainPassword($password)
{
$this->plainPassword = $password;
return $this;
}
@@ -279,6 +279,7 @@ class User implements UserInterface
public function setEmail($email)
{
$this->email = $email;
return $this;
}
@@ -297,6 +298,7 @@ class User implements UserInterface
public function setTitle($title)
{
$this->title = $title;
return $this;
}
@@ -315,6 +317,7 @@ class User implements UserInterface
public function setAvatar($avatar)
{
$this->avatar = $avatar;
return $this;
}
@@ -342,6 +345,7 @@ class User implements UserInterface
public function setRoles(array $roles)
{
$this->roles = $roles;
return $this;
}
@@ -363,6 +367,7 @@ class User implements UserInterface
$preferences = new ArrayCollection($preferences);
}
$this->preferences = $preferences;
return $this;
}
@@ -382,16 +387,17 @@ class User implements UserInterface
}
/**
* @param $name
* @param null $default
* @param string $name
* @param mixed $default
* @return bool|int|null|string
*/
public function getPreferenceValue($name, $default = null)
{
$preference = $this->getPreference($name);
if ($preference === null) {
if (null === $preference) {
return $default;
}
return $preference->getValue();
}
@@ -402,6 +408,7 @@ class User implements UserInterface
public function addPreference(UserPreference $preference)
{
$this->preferences->add($preference);
return $this;
}

View File

@@ -21,8 +21,8 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
class UserPreference
{
const HOURLY_RATE = 'hourly_rate';
const SKIN = 'skin';
public const HOURLY_RATE = 'hourly_rate';
public const SKIN = 'skin';
/**
* @var int
@@ -82,6 +82,7 @@ class UserPreference
public function setId(int $id): UserPreference
{
$this->id = $id;
return $this;
}
@@ -100,6 +101,7 @@ class UserPreference
public function setUser(User $user): UserPreference
{
$this->user = $user;
return $this;
}
@@ -118,6 +120,7 @@ class UserPreference
public function setName(string $name): UserPreference
{
$this->name = $name;
return $this;
}
@@ -143,6 +146,7 @@ class UserPreference
public function setValue($value): UserPreference
{
$this->value = $value;
return $this;
}
@@ -155,6 +159,7 @@ class UserPreference
public function setType(string $type)
{
$this->type = $type;
return $this;
}
@@ -175,6 +180,7 @@ class UserPreference
public function setConstraints(array $constraints)
{
$this->constraints = $constraints;
return $this;
}
@@ -187,6 +193,7 @@ class UserPreference
public function addConstraint(Constraint $constraint)
{
$this->constraints[] = $constraint;
return $this;
}

View File

@@ -16,7 +16,7 @@ use Avanzu\AdminThemeBundle\Model\MenuItemModel;
*/
class ConfigureAdminMenuEvent extends ConfigureMenuEvent
{
const CONFIGURE = 'app.admin_menu_configure';
public const CONFIGURE = 'app.admin_menu_configure';
/**
* This function will either return a MenuItem or null.

View File

@@ -14,5 +14,5 @@ namespace App\Event;
*/
class ConfigureMainMenuEvent extends ConfigureMenuEvent
{
const CONFIGURE = 'app.main_menu_configure';
public const CONFIGURE = 'app.main_menu_configure';
}

View File

@@ -12,7 +12,6 @@ namespace App\Event;
use Avanzu\AdminThemeBundle\Event\SidebarMenuEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
/**
* The ConfigureMenuEvent is used for populating navigations.

View File

@@ -18,7 +18,7 @@ use Symfony\Component\EventDispatcher\Event;
*/
class UserPreferenceEvent extends Event
{
const CONFIGURE = 'app.user_preferences';
public const CONFIGURE = 'app.user_preferences';
/**
* @var User
@@ -64,7 +64,7 @@ class UserPreferenceEvent extends Event
foreach ($this->preferences as $pref) {
if ($pref->getName() == $preference->getName()) {
throw new \InvalidArgumentException(
'Cannot add preference, a preference with the name "'.$preference->getName().'" is already existing'
'Cannot add preference, one with the name "' . $preference->getName() . '" is already existing'
);
}
}

View File

@@ -50,7 +50,7 @@ class NavbarShowUserSubscriber implements EventSubscriberInterface
*/
public function onShowUser(ShowUserEvent $event)
{
if ($this->storage->getToken() === null) {
if (null === $this->storage->getToken()) {
return;
}

View File

@@ -22,7 +22,6 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
*/
class ThemeOptionsSubscriber implements EventSubscriberInterface
{
/**
* @var TokenStorageInterface
*/
@@ -69,11 +68,11 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
$skin = '';
foreach ($user->getPreferences() as $ref) {
$name = $ref->getName();
if ($name === UserPreference::SKIN) {
if (UserPreference::SKIN === $name) {
$skin = 'skin-' . $ref->getValue();
}
if (strpos($name, 'theme.') !== false) {
if (false !== strpos($name, 'theme.')) {
$this->helper->setOption(str_replace('theme.', '', $name), $ref->getValue());
}
}
@@ -97,7 +96,7 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
}
// ignore events like the toolbar where we do not have a token
if ($this->storage->getToken() === null) {
if (null === $this->storage->getToken()) {
return false;
}

View File

@@ -27,7 +27,6 @@ use Symfony\Component\Validator\Constraints\Range;
*/
class UserPreferenceSubscriber implements EventSubscriberInterface
{
/**
* @var EventDispatcherInterface
*/
@@ -127,7 +126,7 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
foreach ($event->getPreferences() as $preference) {
if (isset($prefs[$preference->getName()])) {
/** @var UserPreference $pref */
/* @var UserPreference $pref */
$prefs[$preference->getName()]
->setType($preference->getType())
->setConstraints($preference->getConstraints())
@@ -152,7 +151,7 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
}
// ignore events like the toolbar where we do not have a token
if ($this->storage->getToken() === null) {
if (null === $this->storage->getToken()) {
return false;
}

View File

@@ -24,7 +24,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class ActivityEditForm extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -28,7 +28,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class CustomerEditForm extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -43,7 +43,7 @@ class DocumentationLinkExtension extends AbstractTypeExtension
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefined(array('documentation'));
$resolver->setDefined(['documentation']);
$resolver->setDefaults(['documentation' => null]);
}
}

View File

@@ -25,7 +25,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class InvoiceTemplateForm extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -26,7 +26,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class ProjectEditForm extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -25,7 +25,6 @@ use App\Repository\ActivityRepository;
*/
class TimesheetEditForm extends AbstractType
{
/**
* {@inheritdoc}
*/
@@ -39,7 +38,7 @@ class TimesheetEditForm extends AbstractType
$activity = $entry->getActivity();
}
if ($entry->getEnd() === null || !$options['duration_only']) {
if (null === $entry->getEnd() || !$options['duration_only']) {
$builder->add('begin', DateTimeType::class, [
'label' => 'label.begin',
'widget' => 'single_text',

View File

@@ -33,7 +33,6 @@ use Symfony\Component\Form\FormEvents;
*/
abstract class AbstractToolbarForm extends AbstractType
{
/**
* Dirty hack to enable easy handling of GET form in controller and javascript.
*Cleans up the name of all form elents (and unfortunately of the form itself).
@@ -67,6 +66,7 @@ abstract class AbstractToolbarForm extends AbstractType
$query = new CustomerQuery();
$query->setVisibility(CustomerQuery::SHOW_BOTH); // this field is the reason for the query here
$query->setResultType(CustomerQuery::RESULT_TYPE_QUERYBUILDER);
return $repo->findByQuery($query);
},
]);
@@ -147,6 +147,7 @@ abstract class AbstractToolbarForm extends AbstractType
'query_builder' => function (ProjectRepository $repo) use ($data) {
$qb = $repo->builderForEntityType();
$qb->where('p.customer = :customer')->setParameter('customer', $data['customer']);
return $qb;
},
]);
@@ -173,6 +174,7 @@ abstract class AbstractToolbarForm extends AbstractType
'query_builder' => function (ActivityRepository $repo) use ($data) {
$qb = $repo->builderForEntityType();
$qb->where('a.project = :project')->setParameter('project', $data['project']);
return $qb;
},
]);

View File

@@ -18,7 +18,6 @@ use App\Repository\Query\ActivityQuery;
*/
class ActivityToolbarForm extends AbstractToolbarForm
{
/**
* {@inheritdoc}
*/

View File

@@ -18,7 +18,6 @@ use App\Repository\Query\CustomerQuery;
*/
class CustomerToolbarForm extends AbstractToolbarForm
{
/**
* {@inheritdoc}
*/

View File

@@ -19,9 +19,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class InvoiceToolbarForm extends AbstractToolbarForm
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{

View File

@@ -18,7 +18,6 @@ use App\Repository\Query\ProjectQuery;
*/
class ProjectToolbarForm extends AbstractToolbarForm
{
/**
* {@inheritdoc}
*/

View File

@@ -16,9 +16,8 @@ use Symfony\Component\Form\FormBuilderInterface;
*/
class TimesheetAdminToolbarForm extends TimesheetToolbarForm
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{

View File

@@ -19,9 +19,8 @@ use App\Repository\Query\TimesheetQuery;
*/
class TimesheetToolbarForm extends AbstractToolbarForm
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{

View File

@@ -18,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserToolbarForm extends AbstractToolbarForm
{
/**
* {@inheritdoc}
*/

View File

@@ -16,7 +16,6 @@ use App\Entity\Activity;
*/
class ActivityGroupedWithCustomerNameType extends ActivityType
{
/**
* @param Activity $activity
* @param $key

View File

@@ -20,7 +20,6 @@ use App\Repository\ActivityRepository;
*/
class ActivityType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -19,7 +19,6 @@ use App\Repository\CustomerRepository;
*/
class CustomerType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -50,7 +50,6 @@ class DurationType extends AbstractType
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'label' => 'label.duration',
'constraints' => [new Regex(['pattern' => $this->pattern])],

View File

@@ -19,7 +19,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class InvoiceTemplateType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -19,7 +19,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class LanguageType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -18,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class PageSizeType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -20,7 +20,6 @@ use App\Repository\ProjectRepository;
*/
class ProjectType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -18,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class SkinType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -23,7 +23,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserPreferenceType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
@@ -43,7 +42,7 @@ class UserPreferenceType extends AbstractType
}
$required = true;
if ($preference->getType() == CheckboxType::class) {
if (CheckboxType::class == $preference->getType()) {
$required = false;
}

View File

@@ -18,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserRoleType extends AbstractType
{
/**
* @var string[]
*/
@@ -39,7 +38,7 @@ class UserRoleType extends AbstractType
public function configureOptions(OptionsResolver $resolver)
{
$roles = [];
/* @var string[] $value */
foreach ($this->roles as $key => $value) {
$roles[$key] = $key;
foreach ($value as $value2) {

View File

@@ -19,7 +19,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserType extends AbstractType
{
/**
* {@inheritdoc}
*/
@@ -32,6 +31,7 @@ class UserType extends AbstractType
if (!empty($user->getAlias())) {
return $user->getAlias() . ' (' . $user->getUsername() . ')';
}
return $user->getUsername();
},
]);

View File

@@ -19,7 +19,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class VisibilityType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -18,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class YesNoType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -19,7 +19,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserCreateType extends UserEditType
{
/**
* {@inheritdoc}
*/

View File

@@ -10,7 +10,6 @@
namespace App\Form;
use App\Entity\User;
use App\Form\Type\LanguageType;
use App\Form\Type\YesNoType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
@@ -22,7 +21,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserEditType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -21,7 +21,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserPasswordType extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -21,7 +21,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class UserPreferencesForm extends AbstractType
{
/**
* {@inheritdoc}
*/

View File

@@ -17,7 +17,6 @@ use App\Model\InvoiceModel;
*/
interface CalculatorInterface
{
/**
* Return the timesheet records that will be displayed on the invoice.
*

View File

@@ -20,7 +20,6 @@ use App\Model\InvoiceModel;
*/
class DefaultCalculator implements CalculatorInterface
{
/**
* @var string
*/
@@ -56,6 +55,7 @@ class DefaultCalculator implements CalculatorInterface
foreach ($this->model->getEntries() as $entry) {
$amount += $entry->getRate();
}
return round($amount, 2);
}
@@ -73,11 +73,12 @@ class DefaultCalculator implements CalculatorInterface
public function getTax(): float
{
$vat = $this->getVat();
if ($vat == 0) {
if (0 == $vat) {
return 0;
}
$percent = $vat / 100.00;
return round($this->getSubtotal() * $percent, 2);
}

View File

@@ -16,7 +16,6 @@ use App\Model\InvoiceModel;
*/
interface NumberGeneratorInterface
{
/**
* @param InvoiceModel $model
*/

View File

@@ -50,6 +50,7 @@ class ServiceInvoice
return new $class();
}
}
return null;
}
@@ -72,6 +73,7 @@ class ServiceInvoice
return new $class();
}
}
return null;
}
@@ -97,6 +99,7 @@ class ServiceInvoice
return $action;
}
}
return null;
}
}

View File

@@ -17,7 +17,6 @@ use App\Entity\Timesheet;
*/
class ShortInvoiceCalculator extends DefaultCalculator
{
/**
* @return Timesheet[]
*/
@@ -28,7 +27,7 @@ class ShortInvoiceCalculator extends DefaultCalculator
foreach ($this->model->getEntries() as $entry) {
$timesheet->setRate($timesheet->getRate() + $entry->getRate());
$timesheet->setDuration($timesheet->getDuration() + $entry->getDuration());
if ($timesheet->getActivity() === null) {
if (null === $timesheet->getActivity()) {
$timesheet->setActivity($entry->getActivity());
$timesheet->setEnd($entry->getEnd());
}

View File

@@ -23,16 +23,16 @@ class Kernel extends BaseKernel
{
use MicroKernelTrait;
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function getCacheDir()
{
return $this->getProjectDir().'/var/cache/'.$this->environment;
return $this->getProjectDir() . '/var/cache/' . $this->environment;
}
public function getLogDir()
{
return $this->getProjectDir().'/var/log';
return $this->getProjectDir() . '/var/log';
}
protected function build(ContainerBuilder $container)
@@ -42,7 +42,7 @@ class Kernel extends BaseKernel
public function registerBundles()
{
$contents = require $this->getProjectDir().'/config/bundles.php';
$contents = require $this->getProjectDir() . '/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
@@ -56,27 +56,27 @@ class Kernel extends BaseKernel
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
if (is_dir($confDir.'/packages/'.$this->environment)) {
$loader->load($confDir.'/packages/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$confDir = $this->getProjectDir() . '/config';
$loader->load($confDir . '/packages/*' . self::CONFIG_EXTS, 'glob');
if (is_dir($confDir . '/packages/' . $this->environment)) {
$loader->load($confDir . '/packages/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob');
}
$loader->load($confDir.'/packages/local'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/packages/local' . self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/services' . self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/services_' . $this->environment . self::CONFIG_EXTS, 'glob');
$container->addCompilerPass(new DoctrineCompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -1000);
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
if (is_dir($confDir.'/routes/')) {
$routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
$confDir = $this->getProjectDir() . '/config';
if (is_dir($confDir . '/routes/')) {
$routes->import($confDir . '/routes/*' . self::CONFIG_EXTS, '/', 'glob');
}
if (is_dir($confDir.'/routes/'.$this->environment)) {
$routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
if (is_dir($confDir . '/routes/' . $this->environment)) {
$routes->import($confDir . '/routes/' . $this->environment . '/**/*' . self::CONFIG_EXTS, '/', 'glob');
}
$routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir . '/routes' . self::CONFIG_EXTS, '/', 'glob');
}
}

View File

@@ -44,6 +44,7 @@ class ActivityStatistic
public function setRecordAmount($recordAmount)
{
$this->recordAmount = (int) $recordAmount;
return $this;
}
@@ -64,6 +65,7 @@ class ActivityStatistic
public function setRecordDuration($recordDuration)
{
$this->recordDuration = (int) $recordDuration;
return $this;
}
@@ -84,6 +86,7 @@ class ActivityStatistic
public function setCount($count)
{
$this->count = (int) $count;
return $this;
}
}

View File

@@ -52,6 +52,7 @@ class CustomerStatistic
public function setRecordAmount($recordAmount)
{
$this->recordAmount = (int) $recordAmount;
return $this;
}
@@ -72,6 +73,7 @@ class CustomerStatistic
public function setRecordDuration($recordDuration)
{
$this->recordDuration = (int) $recordDuration;
return $this;
}
@@ -92,6 +94,7 @@ class CustomerStatistic
public function setCount($count)
{
$this->count = (int) $count;
return $this;
}
@@ -110,6 +113,7 @@ class CustomerStatistic
public function setActivityAmount($activityAmount)
{
$this->activityAmount = (int) $activityAmount;
return $this;
}
@@ -128,6 +132,7 @@ class CustomerStatistic
public function setProjectAmount($projectAmount)
{
$this->projectAmount = (int) $projectAmount;
return $this;
}
}

View File

@@ -13,8 +13,6 @@ use App\Entity\Customer;
use App\Entity\InvoiceTemplate;
use App\Entity\Timesheet;
use App\Invoice\CalculatorInterface;
use App\Invoice\DateNumberGenerator;
use App\Invoice\DefaultCalculator;
use App\Invoice\NumberGeneratorInterface;
use App\Repository\Query\InvoiceQuery;
@@ -23,7 +21,6 @@ use App\Repository\Query\InvoiceQuery;
*/
class InvoiceModel
{
/**
* @var Customer
*/
@@ -69,6 +66,7 @@ class InvoiceModel
public function setQuery(InvoiceQuery $query)
{
$this->query = $query;
return $this;
}
@@ -89,6 +87,7 @@ class InvoiceModel
public function setEntries(array $entries)
{
$this->entries = $entries;
return $this;
}
@@ -107,6 +106,7 @@ class InvoiceModel
public function setTemplate($template)
{
$this->template = $template;
return $this;
}
@@ -125,6 +125,7 @@ class InvoiceModel
public function setCustomer($customer)
{
$this->customer = $customer;
return $this;
}
@@ -133,7 +134,7 @@ class InvoiceModel
*/
public function getDueDate(): \DateTime
{
return new \DateTime('+'.$this->getTemplate()->getDueDays().' days');
return new \DateTime('+' . $this->getTemplate()->getDueDays() . ' days');
}
/**
@@ -152,6 +153,7 @@ class InvoiceModel
{
$this->generator = $generator;
$this->generator->setModel($this);
return $this;
}
@@ -171,6 +173,7 @@ class InvoiceModel
{
$this->calculator = $calculator;
$this->calculator->setModel($this);
return $this;
}

View File

@@ -48,6 +48,7 @@ class ProjectStatistic
public function setRecordAmount($recordAmount)
{
$this->recordAmount = (int) $recordAmount;
return $this;
}
@@ -68,6 +69,7 @@ class ProjectStatistic
public function setRecordDuration($recordDuration)
{
$this->recordDuration = (int) $recordDuration;
return $this;
}
@@ -88,6 +90,7 @@ class ProjectStatistic
public function setCount($count)
{
$this->count = (int) $count;
return $this;
}
@@ -106,6 +109,7 @@ class ProjectStatistic
public function setActivityAmount($activityAmount)
{
$this->activityAmount = (int) $activityAmount;
return $this;
}
}

View File

@@ -59,6 +59,7 @@ class Month
public function setTotalDuration($totalDuration)
{
$this->totalDuration = $totalDuration;
return $this;
}
@@ -77,6 +78,7 @@ class Month
public function setTotalRate($totalRate)
{
$this->totalRate = $totalRate;
return $this;
}
}

View File

@@ -46,7 +46,7 @@ class Year
*/
public function setMonth(Month $month)
{
$this->months[(int)$month->getMonth()] = $month;
$this->months[(int) $month->getMonth()] = $month;
return $this;
}

View File

@@ -9,7 +9,7 @@
namespace App\Model;
use \DateTime;
use DateTime;
/**
* Timesheet statistics for one user.

View File

@@ -9,12 +9,7 @@
namespace App\Repository;
use App\Repository\Query\BaseQuery;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
/**
* Class AbstractRepository

View File

@@ -21,7 +21,6 @@ use App\Repository\Query\ActivityQuery;
*/
class ActivityRepository extends AbstractRepository
{
/**
* @param $id
* @return null|Activity
@@ -55,12 +54,12 @@ class ActivityRepository extends AbstractRepository
->setMaxResults(10)
;
if ($user !== null) {
if (null !== $user) {
$qb->andWhere('t.user = :user')
->setParameter('user', $user);
}
if ($startFrom !== null) {
if (null !== $startFrom) {
$qb->andWhere($qb->expr()->gt('t.begin', ':begin'))
->setParameter('begin', $startFrom);
}
@@ -85,7 +84,7 @@ class ActivityRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(a.id) FROM '.Activity::class.' a')
->createQuery('SELECT COUNT(a.id) FROM ' . Activity::class . ' a')
->getSingleScalarResult();
$stats = new ActivityStatistic();
@@ -135,6 +134,7 @@ class ActivityRepository extends AbstractRepository
$query = new ActivityQuery();
$query->setHiddenEntity($entity);
$query->setResultType(ActivityQuery::RESULT_TYPE_QUERYBUILDER);
return $this->findByQuery($query);
}
@@ -152,7 +152,7 @@ class ActivityRepository extends AbstractRepository
->join('p.customer', 'c')
->orderBy('a.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) {
if (ActivityQuery::SHOW_VISIBLE == $query->getVisibility()) {
if (!$query->isExclusiveVisibility()) {
$qb->andWhere('c.visible = 1');
$qb->andWhere('p.visible = 1');
@@ -161,17 +161,17 @@ class ActivityRepository extends AbstractRepository
/** @var Activity $entity */
$entity = $query->getHiddenEntity();
if ($entity !== null) {
if (null !== $entity) {
$qb->orWhere('a.id = :activity')->setParameter('activity', $entity);
}
} elseif ($query->getVisibility() == ActivityQuery::SHOW_HIDDEN) {
} elseif (ActivityQuery::SHOW_HIDDEN == $query->getVisibility()) {
$qb->andWhere('a.visible = 0');
}
if ($query->getProject() !== null) {
if (null !== $query->getProject()) {
$qb->andWhere('a.project = :project')
->setParameter('project', $query->getProject());
} elseif ($query->getCustomer() !== null) {
} elseif (null !== $query->getCustomer()) {
$qb->andWhere('p.customer = :customer')
->setParameter('customer', $query->getCustomer());
}

View File

@@ -22,7 +22,6 @@ use App\Repository\Query\CustomerQuery;
*/
class CustomerRepository extends AbstractRepository
{
/**
* @param $id
* @return null|Customer
@@ -41,11 +40,12 @@ class CustomerRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(c.id) FROM '.Customer::class.' c')
->createQuery('SELECT COUNT(c.id) FROM ' . Customer::class . ' c')
->getSingleScalarResult();
$stats = new CustomerStatistic();
$stats->setCount($countAll);
return $stats;
}
@@ -101,6 +101,7 @@ class CustomerRepository extends AbstractRepository
$query = new CustomerQuery();
$query->setHiddenEntity($entity);
$query->setResultType(CustomerQuery::RESULT_TYPE_QUERYBUILDER);
return $this->findByQuery($query);
}
@@ -116,15 +117,15 @@ class CustomerRepository extends AbstractRepository
->from(Customer::class, 'c')
->orderBy('c.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() == CustomerQuery::SHOW_VISIBLE) {
if (CustomerQuery::SHOW_VISIBLE == $query->getVisibility()) {
$qb->andWhere('c.visible = 1');
/** @var Customer $entity */
$entity = $query->getHiddenEntity();
if ($entity!== null) {
if (null !== $entity) {
$qb->orWhere('c.id = :customer')->setParameter('customer', $entity);
}
} elseif ($query->getVisibility() == CustomerQuery::SHOW_HIDDEN) {
} elseif (CustomerQuery::SHOW_HIDDEN == $query->getVisibility()) {
$qb->andWhere('c.visible = 0');
}

View File

@@ -18,7 +18,6 @@ use Doctrine\ORM\Query;
*/
class InvoiceTemplateRepository extends AbstractRepository
{
/**
* @return bool
*/

View File

@@ -21,7 +21,6 @@ use App\Repository\Query\ProjectQuery;
*/
class ProjectRepository extends AbstractRepository
{
/**
* @param $id
* @return null|Project
@@ -40,11 +39,12 @@ class ProjectRepository extends AbstractRepository
public function getGlobalStatistics()
{
$countAll = $this->getEntityManager()
->createQuery('SELECT COUNT(p.id) FROM '.Project::class.' p')
->createQuery('SELECT COUNT(p.id) FROM ' . Project::class . ' p')
->getSingleScalarResult();
$stats = new ProjectStatistic();
$stats->setCount($countAll);
return $stats;
}
@@ -94,6 +94,7 @@ class ProjectRepository extends AbstractRepository
$query = new ProjectQuery();
$query->setHiddenEntity($entity);
$query->setResultType(ProjectQuery::RESULT_TYPE_QUERYBUILDER);
return $this->findByQuery($query);
}
@@ -112,7 +113,7 @@ class ProjectRepository extends AbstractRepository
->join('p.customer', 'c')
->orderBy('p.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() == ProjectQuery::SHOW_VISIBLE) {
if (ProjectQuery::SHOW_VISIBLE == $query->getVisibility()) {
if (!$query->isExclusiveVisibility()) {
$qb->andWhere('c.visible = 1');
}
@@ -120,17 +121,17 @@ class ProjectRepository extends AbstractRepository
/** @var Project $entity */
$entity = $query->getHiddenEntity();
if ($entity !== null) {
if (null !== $entity) {
$qb->orWhere('p.id = :project')->setParameter('project', $entity);
}
// TODO check for visibility of customer
} elseif ($query->getVisibility() == ProjectQuery::SHOW_HIDDEN) {
} elseif (ProjectQuery::SHOW_HIDDEN == $query->getVisibility()) {
$qb->andWhere('p.visible = 0');
// TODO check for visibility of customer
}
if ($query->getCustomer() !== null) {
if (null !== $query->getCustomer()) {
$qb->andWhere('p.customer = :customer')
->setParameter('customer', $query->getCustomer());
}

View File

@@ -9,7 +9,6 @@
namespace App\Repository\Query;
use App\Entity\Customer;
use App\Entity\Project;
/**
@@ -17,7 +16,6 @@ use App\Entity\Project;
*/
class ActivityQuery extends ProjectQuery
{
/**
* @var Project
*/
@@ -38,6 +36,7 @@ class ActivityQuery extends ProjectQuery
public function setProject(Project $project = null)
{
$this->project = $project;
return $this;
}
}

View File

@@ -14,17 +14,17 @@ namespace App\Repository\Query;
*/
class BaseQuery
{
const ORDER_ASC = 'ASC';
const ORDER_DESC = 'DESC';
public const ORDER_ASC = 'ASC';
public const ORDER_DESC = 'DESC';
const DEFAULT_PAGESIZE = 25;
const DEFAULT_PAGE = 1;
public const DEFAULT_PAGESIZE = 25;
public const DEFAULT_PAGE = 1;
const RESULT_TYPE_PAGER = 'PagerFanta';
const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
public const RESULT_TYPE_PAGER = 'PagerFanta';
public const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
/**
* @var \stdClass
* @var object
*/
protected $hiddenEntity;
/**
@@ -62,7 +62,8 @@ class BaseQuery
*/
public function setPage($page)
{
$this->page = (int)$page;
$this->page = (int) $page;
return $this;
}
@@ -80,9 +81,10 @@ class BaseQuery
*/
public function setPageSize($pageSize)
{
if (!empty($pageSize) && (int)$pageSize > 0) {
$this->pageSize = (int)$pageSize;
if (!empty($pageSize) && (int) $pageSize > 0) {
$this->pageSize = (int) $pageSize;
}
return $this;
}
@@ -103,6 +105,7 @@ class BaseQuery
public function setOrderBy($orderBy)
{
$this->orderBy = $orderBy;
return $this;
}
@@ -123,6 +126,7 @@ class BaseQuery
if (in_array($order, [self::ORDER_ASC, self::ORDER_DESC])) {
$this->order = $order;
}
return $this;
}
@@ -143,11 +147,12 @@ class BaseQuery
if (in_array($resultType, [self::RESULT_TYPE_PAGER, self::RESULT_TYPE_QUERYBUILDER])) {
$this->resultType = $resultType;
}
return $this;
}
/**
* @return \stdClass
* @return object
*/
public function getHiddenEntity()
{
@@ -155,12 +160,13 @@ class BaseQuery
}
/**
* @param \stdClass $hiddenEntity
* @param object $hiddenEntity
* @return BaseQuery
*/
public function setHiddenEntity($hiddenEntity)
{
$this->hiddenEntity = $hiddenEntity;
return $this;
}
}

View File

@@ -16,7 +16,6 @@ use App\Entity\InvoiceTemplate;
*/
class InvoiceQuery extends TimesheetQuery
{
/**
* @var InvoiceTemplate
*/
@@ -42,6 +41,7 @@ class InvoiceQuery extends TimesheetQuery
public function setTemplate($template)
{
$this->template = $template;
return $this;
}
@@ -60,6 +60,7 @@ class InvoiceQuery extends TimesheetQuery
public function setTemplates(array $templates)
{
$this->templates = $templates;
return $this;
}
}

View File

@@ -16,7 +16,6 @@ use App\Entity\Customer;
*/
class ProjectQuery extends VisibilityQuery
{
/**
* @var Customer
*/
@@ -37,6 +36,7 @@ class ProjectQuery extends VisibilityQuery
public function setCustomer(Customer $customer = null)
{
$this->customer = $customer;
return $this;
}
}

View File

@@ -10,19 +10,16 @@
namespace App\Repository\Query;
use App\Entity\User;
use App\Repository\Query\BaseQuery;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
/**
* Can be used for advanced timesheet repository queries.
*/
class TimesheetQuery extends ActivityQuery
{
const STATE_ALL = 1;
const STATE_RUNNING = 2;
const STATE_STOPPED = 3;
public const STATE_ALL = 1;
public const STATE_RUNNING = 2;
public const STATE_STOPPED = 3;
/**
* Overwritten for different default order
@@ -70,6 +67,7 @@ class TimesheetQuery extends ActivityQuery
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
@@ -90,6 +88,7 @@ class TimesheetQuery extends ActivityQuery
public function setActivity(Activity $activity = null)
{
$this->activity = $activity;
return $this;
}
@@ -134,6 +133,7 @@ class TimesheetQuery extends ActivityQuery
public function setBegin($begin)
{
$this->begin = $begin;
return $this;
}
@@ -152,6 +152,7 @@ class TimesheetQuery extends ActivityQuery
public function setEnd($end)
{
$this->end = $end;
return $this;
}
}

View File

@@ -14,7 +14,6 @@ namespace App\Repository\Query;
*/
class UserQuery extends VisibilityQuery
{
/**
* @var string
*/
@@ -34,9 +33,10 @@ class UserQuery extends VisibilityQuery
*/
public function setRole($role)
{
if (strpos($role, 'ROLE_') !== false || $role === null) {
if (false !== strpos($role, 'ROLE_') || null === $role) {
$this->role = $role;
}
return $this;
}
}

View File

@@ -14,12 +14,12 @@ namespace App\Repository\Query;
*/
class VisibilityQuery extends BaseQuery
{
const SHOW_VISIBLE = 1;
const SHOW_HIDDEN = 2;
const SHOW_BOTH = 3;
public const SHOW_VISIBLE = 1;
public const SHOW_HIDDEN = 2;
public const SHOW_BOTH = 3;
/**
* @var integer
* @var int
*/
protected $visibility = self::SHOW_VISIBLE;
/**
@@ -70,6 +70,7 @@ class VisibilityQuery extends BaseQuery
public function setExclusiveVisibility($exclusiveVisibility)
{
$this->exclusiveVisibility = (bool) $exclusiveVisibility;
return $this;
}
}

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