release 2.0 beta (#3722)
* remove twitter link * remove WIP file * adjust release draft message * reset code coverage threshold back to 0.5 * changed wordings * re-activate wizard for fixture accounts * fix repo url and license * license identifier * bump version * moved Kimai 1 import command from core to plugin * do not traverse into invoice template subdirectories (#3735) * fix branch alias * composer update * switch language on wizard select * new twig function to create qr code * fix daily stats in timesheet listing * improved html invoice templates
This commit is contained in:
@@ -15,6 +15,9 @@ use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* @template-implements PasswordUpgraderInterface<User>
|
||||
*/
|
||||
class ApiUserRepository implements UserLoaderInterface, PasswordUpgraderInterface
|
||||
{
|
||||
public function __construct(private UserRepository $userRepository)
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Repository;
|
||||
|
||||
use App\Model\InvoiceDocument;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
final class InvoiceDocumentRepository
|
||||
{
|
||||
@@ -21,6 +22,9 @@ final class InvoiceDocumentRepository
|
||||
*/
|
||||
private array $documentDirs = [];
|
||||
|
||||
/**
|
||||
* @param array<string> $directories
|
||||
*/
|
||||
public function __construct(array $directories)
|
||||
{
|
||||
foreach ($directories as $directory) {
|
||||
@@ -31,23 +35,19 @@ final class InvoiceDocumentRepository
|
||||
/**
|
||||
* @CloudRequired
|
||||
*/
|
||||
public function addDirectory(string $directory)
|
||||
public function addDirectory(string $directory): void
|
||||
{
|
||||
$this->documentDirs[] = $directory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @CloudRequired
|
||||
*/
|
||||
public function removeDirectory(string $directory)
|
||||
public function removeDirectory(string $directory): void
|
||||
{
|
||||
if (($key = array_search($directory, $this->documentDirs)) !== false) {
|
||||
unset($this->documentDirs[$key]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,12 @@ final class InvoiceDocumentRepository
|
||||
throw new \InvalidArgumentException('Cannot delete built-in invoice template');
|
||||
}
|
||||
|
||||
@unlink(realpath($invoiceDocument->getFilename()));
|
||||
$realpath = realpath($invoiceDocument->getFilename());
|
||||
if ($realpath === false) {
|
||||
throw new \InvalidArgumentException('Template does not exist: ' . $invoiceDocument->getFilename());
|
||||
}
|
||||
|
||||
@unlink($realpath);
|
||||
}
|
||||
|
||||
public function getUploadDirectory(): string
|
||||
@@ -135,6 +140,7 @@ final class InvoiceDocumentRepository
|
||||
/**
|
||||
* Returns an array of invoice documents.
|
||||
*
|
||||
* @param array<string> $paths
|
||||
* @return InvoiceDocument[]
|
||||
*/
|
||||
private function findByPaths(array $paths): array
|
||||
@@ -153,7 +159,8 @@ final class InvoiceDocumentRepository
|
||||
continue;
|
||||
}
|
||||
|
||||
$finder = Finder::create()->ignoreDotFiles(true)->files()->in($searchDir)->name('*.*');
|
||||
$finder = Finder::create()->ignoreDotFiles(true)->files()->in($searchDir)->depth(0)->name('*.*');
|
||||
/** @var SplFileInfo $file */
|
||||
foreach ($finder->getIterator() as $file) {
|
||||
$doc = new InvoiceDocument($file);
|
||||
// the first found invoice document wins
|
||||
|
||||
@@ -24,6 +24,9 @@ final class LoaderPaginator implements PaginatorInterface
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array-key, iterable<mixed>>
|
||||
*/
|
||||
public function getSlice(int $offset, int $length): iterable
|
||||
{
|
||||
$query = $this->query
|
||||
@@ -34,13 +37,17 @@ final class LoaderPaginator implements PaginatorInterface
|
||||
return $this->getResults($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Query<null, mixed> $query
|
||||
* @return iterable<array-key, iterable<mixed>>
|
||||
*/
|
||||
private function getResults(Query $query)
|
||||
{
|
||||
$results = $query->execute();
|
||||
|
||||
$this->loader->loadResults($results);
|
||||
|
||||
return $results;
|
||||
return $results; // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
public function getAll(): iterable
|
||||
|
||||
@@ -23,6 +23,9 @@ final class QueryBuilderPaginator implements PaginatorInterface
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array-key, iterable<mixed>>
|
||||
*/
|
||||
public function getSlice(int $offset, int $length): iterable
|
||||
{
|
||||
$query = $this->query
|
||||
@@ -33,9 +36,13 @@ final class QueryBuilderPaginator implements PaginatorInterface
|
||||
return $this->getResults($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Query<null, mixed> $query
|
||||
* @return iterable<array-key, iterable<mixed>>
|
||||
*/
|
||||
private function getResults(Query $query)
|
||||
{
|
||||
return $query->execute();
|
||||
return $query->execute(); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
public function getAll(): iterable
|
||||
|
||||
@@ -34,6 +34,7 @@ use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
/**
|
||||
* @extends \Doctrine\ORM\EntityRepository<User>
|
||||
* @template-implements PasswordUpgraderInterface<User>
|
||||
*/
|
||||
class UserRepository extends EntityRepository implements UserLoaderInterface, UserProviderInterface, PasswordUpgraderInterface
|
||||
{
|
||||
@@ -58,7 +59,7 @@ class UserRepository extends EntityRepository implements UserLoaderInterface, Us
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
||||
public function upgradePassword(PasswordAuthenticatedUserInterface|UserInterface $user, string $newHashedPassword): void
|
||||
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
|
||||
{
|
||||
if (!($user instanceof User)) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user