Compare commits
18 Commits
8ec4e4eb59
...
a9ecdfe4bb
Author | SHA1 | Date |
---|---|---|
|
a9ecdfe4bb | |
|
10a966c6ad | |
|
3b63a73161 | |
|
4e453a73a6 | |
|
96cf0b7dd5 | |
|
b2e85211a7 | |
|
3dacfb3e54 | |
|
c9ccebc8f3 | |
|
b6aaf6b2e1 | |
|
793e4bacbd | |
|
6c44a25638 | |
|
8609f1e9c6 | |
|
0d07975e53 | |
|
f7d9328447 | |
|
d26bdd72fb | |
|
ff40b9e805 | |
|
92997aa78f | |
|
ee02b8df3a |
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
use App\Actions\DbMaintainAction;
|
use App\Actions\DbMaintainAction;
|
||||||
|
use App\Form\Actions\PreventionRememberAction;
|
||||||
use App\Initialize\InitializeMembers;
|
use App\Initialize\InitializeMembers;
|
||||||
use App\Invoice\Actions\InvoiceSendAction;
|
use App\Invoice\Actions\InvoiceSendAction;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
|
@ -19,6 +20,7 @@ class Kernel extends ConsoleKernel
|
||||||
InvoiceSendAction::class,
|
InvoiceSendAction::class,
|
||||||
InitializeMembers::class,
|
InitializeMembers::class,
|
||||||
DbMaintainAction::class,
|
DbMaintainAction::class,
|
||||||
|
PreventionRememberAction::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +32,7 @@ class Kernel extends ConsoleKernel
|
||||||
{
|
{
|
||||||
$schedule->command(DbMaintainAction::class)->daily();
|
$schedule->command(DbMaintainAction::class)->daily();
|
||||||
$schedule->command(InitializeMembers::class)->dailyAt('03:00');
|
$schedule->command(InitializeMembers::class)->dailyAt('03:00');
|
||||||
|
$schedule->command(PreventionRememberAction::class)->dailyAt('11:00');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -155,8 +155,9 @@ class AddressBookBackend extends AbstractBackend
|
||||||
* If the backend supports this, it may allow for some speed-ups.
|
* If the backend supports this, it may allow for some speed-ups.
|
||||||
*
|
*
|
||||||
* @param mixed $addressBookId
|
* @param mixed $addressBookId
|
||||||
|
* @param array<int, string> $uris
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<int, mixed>
|
||||||
*/
|
*/
|
||||||
public function getMultipleCards($addressBookId, array $uris)
|
public function getMultipleCards($addressBookId, array $uris)
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,10 +136,11 @@ class Principal implements PrincipalBackendInterface
|
||||||
*
|
*
|
||||||
* @param string $principal
|
* @param string $principal
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<int, string>|null
|
||||||
*/
|
*/
|
||||||
public function getGroupMemberSet($principal)
|
public function getGroupMemberSet($principal)
|
||||||
{
|
{
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,7 +148,7 @@ class Principal implements PrincipalBackendInterface
|
||||||
*
|
*
|
||||||
* @param string $principal
|
* @param string $principal
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<int, string>|null
|
||||||
*/
|
*/
|
||||||
public function getGroupMembership($principal)
|
public function getGroupMembership($principal)
|
||||||
{
|
{
|
||||||
|
@ -155,7 +156,7 @@ class Principal implements PrincipalBackendInterface
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['addressbooks/'.$matches[1]];
|
return ['addressbooks/' . $matches[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,6 +165,8 @@ class Principal implements PrincipalBackendInterface
|
||||||
* The principals should be passed as a list of uri's.
|
* The principals should be passed as a list of uri's.
|
||||||
*
|
*
|
||||||
* @param string $principal
|
* @param string $principal
|
||||||
|
* @param array<int, string> $members
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setGroupMemberSet($principal, array $members)
|
public function setGroupMemberSet($principal, array $members)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +179,7 @@ class Principal implements PrincipalBackendInterface
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'{DAV:}displayname' => $user->name,
|
'{DAV:}displayname' => $user->name,
|
||||||
'uri' => 'principals/'.$user->email,
|
'uri' => 'principals/' . $user->email,
|
||||||
'{http://sabredav.org/ns}email-address' => $user->email,
|
'{http://sabredav.org/ns}email-address' => $user->email,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use Sabre\CardDAV\AddressBookRoot;
|
||||||
use Sabre\CardDAV\Plugin as CardDAVPlugin;
|
use Sabre\CardDAV\Plugin as CardDAVPlugin;
|
||||||
use Sabre\DAV\Auth\Plugin as AuthPlugin;
|
use Sabre\DAV\Auth\Plugin as AuthPlugin;
|
||||||
use Sabre\DAV\Browser\Plugin as BrowserPlugin;
|
use Sabre\DAV\Browser\Plugin as BrowserPlugin;
|
||||||
|
use Sabre\DAV\ServerPlugin;
|
||||||
use Sabre\DAVACL\AbstractPrincipalCollection;
|
use Sabre\DAVACL\AbstractPrincipalCollection;
|
||||||
use Sabre\DAVACL\Plugin as AclPlugin;
|
use Sabre\DAVACL\Plugin as AclPlugin;
|
||||||
use Sabre\DAVACL\PrincipalCollection;
|
use Sabre\DAVACL\PrincipalCollection;
|
||||||
|
@ -50,6 +51,9 @@ class ServiceProvider extends BaseServiceProvider
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, ServerPlugin>
|
||||||
|
*/
|
||||||
private function plugins(): array
|
private function plugins(): array
|
||||||
{
|
{
|
||||||
$authBackend = new AuthBackend();
|
$authBackend = new AuthBackend();
|
||||||
|
|
|
@ -12,15 +12,14 @@ class Handler extends ExceptionHandler
|
||||||
/**
|
/**
|
||||||
* A list of the exception types that are not reported.
|
* A list of the exception types that are not reported.
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var array<int, class-string<Throwable>>
|
||||||
*/
|
*/
|
||||||
protected $dontReport = [
|
protected $dontReport = [];
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of the inputs that are never flashed for validation exceptions.
|
* A list of the inputs that are never flashed for validation exceptions.
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var array<int, string>
|
||||||
*/
|
*/
|
||||||
protected $dontFlash = [
|
protected $dontFlash = [
|
||||||
'password',
|
'password',
|
||||||
|
|
|
@ -35,6 +35,8 @@ class FormStoreAction
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => 'nullable|array',
|
'export' => 'nullable|array',
|
||||||
|
'needs_prevention' => 'present|boolean',
|
||||||
|
'prevention_text' => 'array',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ class FormUpdateAction
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => 'nullable|array',
|
'export' => 'nullable|array',
|
||||||
|
'needs_prevention' => 'present|boolean',
|
||||||
|
'prevention_text' => 'array',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form\Actions;
|
||||||
|
|
||||||
|
use App\Form\Models\Participant;
|
||||||
|
use App\Prevention\Mails\PreventionRememberMail;
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class PreventionRememberAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public string $commandSignature = 'prevention:remember';
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$query = Participant::whereHas('form', fn ($form) => $form->where('needs_prevention', true))
|
||||||
|
->where(
|
||||||
|
fn ($q) => $q
|
||||||
|
->where('last_remembered_at', '<=', now()->subWeeks(2))
|
||||||
|
->orWhereNull('last_remembered_at')
|
||||||
|
);
|
||||||
|
foreach ($query->get() as $participant) {
|
||||||
|
if (count($participant->preventions()) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = app(PreventionSettings::class)->refresh()->formmail
|
||||||
|
->placeholder('formname', $participant->form->name)
|
||||||
|
->append($participant->form->prevention_text);
|
||||||
|
|
||||||
|
if ($participant->getFields()->getMailRecipient() === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mail::send(new PreventionRememberMail($participant, $body));
|
||||||
|
|
||||||
|
$participant->update(['last_remembered_at' => now()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace App\Form\Models;
|
||||||
use App\Form\Data\ExportData;
|
use App\Form\Data\ExportData;
|
||||||
use App\Form\Data\FieldCollection;
|
use App\Form\Data\FieldCollection;
|
||||||
use App\Form\Data\FormConfigData;
|
use App\Form\Data\FormConfigData;
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
use Cviebrock\EloquentSluggable\Sluggable;
|
use Cviebrock\EloquentSluggable\Sluggable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
@ -16,6 +17,7 @@ use Spatie\MediaLibrary\InteractsWithMedia;
|
||||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
use Zoomyboy\MedialibraryHelper\DefersUploads;
|
use Zoomyboy\MedialibraryHelper\DefersUploads;
|
||||||
|
|
||||||
|
/** @todo replace editor content with EditorData cast */
|
||||||
class Form extends Model implements HasMedia
|
class Form extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
@ -35,6 +37,8 @@ class Form extends Model implements HasMedia
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
'export' => ExportData::class,
|
'export' => ExportData::class,
|
||||||
|
'needs_prevention' => 'boolean',
|
||||||
|
'prevention_text' => EditorData::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
|
|
|
@ -6,14 +6,17 @@ use App\Form\Data\FieldCollection;
|
||||||
use App\Form\Data\FormConfigData;
|
use App\Form\Data\FormConfigData;
|
||||||
use App\Form\Mails\ConfirmRegistrationMail;
|
use App\Form\Mails\ConfirmRegistrationMail;
|
||||||
use App\Form\Scopes\ParticipantFilterScope;
|
use App\Form\Scopes\ParticipantFilterScope;
|
||||||
|
use App\Member\Member;
|
||||||
|
use App\Prevention\Contracts\Preventable;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
class Participant extends Model
|
class Participant extends Model implements Preventable
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
@ -21,6 +24,7 @@ class Participant extends Model
|
||||||
|
|
||||||
public $casts = [
|
public $casts = [
|
||||||
'data' => 'json',
|
'data' => 'json',
|
||||||
|
'last_remembered_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +52,14 @@ class Participant extends Model
|
||||||
return $filter->apply($query);
|
return $filter->apply($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Member, self>
|
||||||
|
*/
|
||||||
|
public function member(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Member::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function getFields(): FieldCollection
|
public function getFields(): FieldCollection
|
||||||
{
|
{
|
||||||
return FieldCollection::fromRequest($this->form, $this->data);
|
return FieldCollection::fromRequest($this->form, $this->data);
|
||||||
|
@ -70,6 +82,29 @@ class Participant extends Model
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mail::to($this->getFields()->getMailRecipient())->queue(new ConfirmRegistrationMail($this));
|
Mail::to($this->getMailRecipient())->queue(new ConfirmRegistrationMail($this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function preventableLayout(): string
|
||||||
|
{
|
||||||
|
return 'mail.prevention.prevention-remember-participant';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function preventions(): array
|
||||||
|
{
|
||||||
|
return $this->member?->preventions($this->form->from) ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailRecipient(): stdClass
|
||||||
|
{
|
||||||
|
return $this->getFields()->getMailRecipient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function preventableSubject(): string
|
||||||
|
{
|
||||||
|
return 'Nachweise erforderlich für deine Anmeldung zu ' . $this->form->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use App\Form\Scopes\FormFilterScope;
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
use App\Form\Models\Formtemplate;
|
use App\Form\Models\Formtemplate;
|
||||||
use App\Group;
|
use App\Group;
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
use App\Lib\HasMeta;
|
use App\Lib\HasMeta;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ class FormResource extends JsonResource
|
||||||
'is_private' => $this->is_private,
|
'is_private' => $this->is_private,
|
||||||
'has_nami_field' => $this->getFields()->hasNamiField(),
|
'has_nami_field' => $this->getFields()->hasNamiField(),
|
||||||
'export' => $this->export,
|
'export' => $this->export,
|
||||||
|
'needs_prevention' => $this->needs_prevention,
|
||||||
|
'prevention_text' => $this->prevention_text,
|
||||||
'links' => [
|
'links' => [
|
||||||
'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
|
'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
|
||||||
'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
|
'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
|
||||||
|
@ -93,6 +96,7 @@ class FormResource extends JsonResource
|
||||||
'config' => null,
|
'config' => null,
|
||||||
'header_image' => null,
|
'header_image' => null,
|
||||||
'mailattachments' => [],
|
'mailattachments' => [],
|
||||||
|
'prevention_text' => EditorData::default(),
|
||||||
'id' => null,
|
'id' => null,
|
||||||
'export' => ExportData::from([]),
|
'export' => ExportData::from([]),
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Editor;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
|
||||||
|
/** @todo replace blocks with actual block data classes */
|
||||||
|
class EditorData extends Data implements Editorable
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @param array<int, mixed> $blocks */
|
||||||
|
public function __construct(
|
||||||
|
public string $version,
|
||||||
|
public array $blocks,
|
||||||
|
public int $time
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function placeholder(string $search, string $replacement): self
|
||||||
|
{
|
||||||
|
$replacedBlocks = str(json_encode($this->blocks))->replace('{' . $search . '}', $replacement);
|
||||||
|
$this->blocks = json_decode($replacedBlocks, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, string> $wanted
|
||||||
|
*/
|
||||||
|
public function hasAll(array $wanted): bool
|
||||||
|
{
|
||||||
|
return collect($wanted)->first(fn ($search) => !str(json_encode($this->blocks))->contains($search)) === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function default(): self
|
||||||
|
{
|
||||||
|
return static::from([
|
||||||
|
'version' => '1.0',
|
||||||
|
'blocks' => [],
|
||||||
|
'time' => 0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function append(Editorable $editorable): self
|
||||||
|
{
|
||||||
|
$this->blocks = array_merge($this->blocks, $editorable->toEditorData()->blocks);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, string> $replacements
|
||||||
|
*/
|
||||||
|
public function replaceWithList(string $blockContent, array $replacements): self
|
||||||
|
{
|
||||||
|
$this->blocks = collect($this->blocks)->map(function ($block) use ($blockContent, $replacements) {
|
||||||
|
if (data_get($block, 'type') !== 'paragraph') {
|
||||||
|
return $block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_get($block, 'data.text') === '{' . $blockContent . '}') {
|
||||||
|
return [
|
||||||
|
...((array)$block),
|
||||||
|
'type' => 'list',
|
||||||
|
'data' => [
|
||||||
|
'style' => 'unordered',
|
||||||
|
'items' => collect($replacements)->map(fn ($replacement) => [
|
||||||
|
'content' => $replacement,
|
||||||
|
'items' => [],
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toEditorData(): EditorData
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Editor;
|
||||||
|
|
||||||
|
interface Editorable
|
||||||
|
{
|
||||||
|
public function toEditorData(): EditorData;
|
||||||
|
}
|
|
@ -23,7 +23,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Laravel\Scout\Attributes\SearchUsingFullText;
|
|
||||||
use Laravel\Scout\Searchable;
|
use Laravel\Scout\Searchable;
|
||||||
use Sabre\VObject\Component\VCard;
|
use Sabre\VObject\Component\VCard;
|
||||||
use Sabre\VObject\Reader;
|
use Sabre\VObject\Reader;
|
||||||
|
@ -33,6 +32,7 @@ use Zoomyboy\Osm\Coordinate;
|
||||||
use Zoomyboy\Osm\Geolocatable;
|
use Zoomyboy\Osm\Geolocatable;
|
||||||
use Zoomyboy\Osm\HasGeolocation;
|
use Zoomyboy\Osm\HasGeolocation;
|
||||||
use Zoomyboy\Phone\HasPhoneNumbers;
|
use Zoomyboy\Phone\HasPhoneNumbers;
|
||||||
|
use App\Prevention\Enums\Prevention;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string $subscription_name
|
* @property string $subscription_name
|
||||||
|
@ -341,6 +341,37 @@ class Member extends Model implements Geolocatable
|
||||||
return $query->where('bill_kind', '!=', null)->where('subscription_id', '!=', null);
|
return $query->where('bill_kind', '!=', null)->where('subscription_id', '!=', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, Prevention>
|
||||||
|
*/
|
||||||
|
public function preventions(?Carbon $date = null): array
|
||||||
|
{
|
||||||
|
$date = $date ?: now();
|
||||||
|
if (!$this->isLeader()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var array<int, Prevention> */
|
||||||
|
$preventions = [];
|
||||||
|
|
||||||
|
if ($this->efz === null || $this->efz->diffInYears($date) >= 5) {
|
||||||
|
$preventions[] = Prevention::EFZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->more_ps_at === null) {
|
||||||
|
if ($this->ps_at === null || $this->ps_at->diffInYears($date) >= 5) {
|
||||||
|
$preventions[] = Prevention::PS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($this->more_ps_at === null || $this->more_ps_at->diffInYears($date) >= 5) {
|
||||||
|
$preventions[] = Prevention::MOREPS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $preventions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Builder<self> $query
|
* @param Builder<self> $query
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Actions;
|
||||||
|
|
||||||
|
use Inertia\Inertia;
|
||||||
|
use Inertia\Response;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class PreventionIndexAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public function handle(): Response
|
||||||
|
{
|
||||||
|
session()->put('menu', 'setting');
|
||||||
|
session()->put('title', 'Prävention');
|
||||||
|
|
||||||
|
return Inertia::render('setting/Prevention');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Actions;
|
||||||
|
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class SettingApiAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public function handle(): JsonResponse
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'data' => app(PreventionSettings::class)->toArray(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Actions;
|
||||||
|
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
|
use App\Lib\Events\Succeeded;
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
|
use Lorisleiva\Actions\ActionRequest;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class SettingStoreAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'formmail' => 'array',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ActionRequest $request): void
|
||||||
|
{
|
||||||
|
$settings = app(PreventionSettings::class);
|
||||||
|
$settings->formmail = EditorData::from($request->formmail);
|
||||||
|
$settings->save();
|
||||||
|
|
||||||
|
Succeeded::message('Einstellungen gespeichert.')->dispatch();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Contracts;
|
||||||
|
|
||||||
|
use App\Prevention\Enums\Prevention;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
interface Preventable
|
||||||
|
{
|
||||||
|
|
||||||
|
public function preventableLayout(): string;
|
||||||
|
public function preventableSubject(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, Prevention>
|
||||||
|
*/
|
||||||
|
public function preventions(): array;
|
||||||
|
|
||||||
|
public function getMailRecipient(): stdClass;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Enums;
|
||||||
|
|
||||||
|
enum Prevention
|
||||||
|
{
|
||||||
|
case EFZ;
|
||||||
|
case PS;
|
||||||
|
case MOREPS;
|
||||||
|
|
||||||
|
public function text(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
static::EFZ => 'erweitertes Führungszeugnis',
|
||||||
|
static::PS => 'Präventionsschulung Basis Plus',
|
||||||
|
static::MOREPS => 'Präventionsschulung (Auffrischung)',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention\Mails;
|
||||||
|
|
||||||
|
use App\Invoice\InvoiceSettings;
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
|
use App\Prevention\Contracts\Preventable;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Attachment;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class PreventionRememberMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public InvoiceSettings $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*/
|
||||||
|
public function __construct(public Preventable $preventable, public EditorData $bodyText)
|
||||||
|
{
|
||||||
|
$this->settings = app(InvoiceSettings::class);
|
||||||
|
$this->bodyText = $this->bodyText
|
||||||
|
->replaceWithList('wanted', collect($preventable->preventions())->map(fn ($prevention) => $prevention->text())->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return (new Envelope(
|
||||||
|
subject: $this->preventable->preventableSubject(),
|
||||||
|
))->to($this->preventable->getMailRecipient()->email, $this->preventable->getMailRecipient()->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
markdown: $this->preventable->preventableLayout(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the attachments for the message.
|
||||||
|
*
|
||||||
|
* @return array<int, Attachment>
|
||||||
|
*/
|
||||||
|
public function attachments(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Prevention;
|
||||||
|
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
|
use App\Prevention\Actions\PreventionIndexAction;
|
||||||
|
use App\Setting\Contracts\Indexable;
|
||||||
|
use App\Setting\LocalSettings;
|
||||||
|
|
||||||
|
class PreventionSettings extends LocalSettings implements Indexable
|
||||||
|
{
|
||||||
|
|
||||||
|
public EditorData $formmail;
|
||||||
|
|
||||||
|
public static function group(): string
|
||||||
|
{
|
||||||
|
return 'prevention';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function slug(): string
|
||||||
|
{
|
||||||
|
return 'prevention';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function indexAction(): string
|
||||||
|
{
|
||||||
|
return PreventionIndexAction::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function title(): string
|
||||||
|
{
|
||||||
|
return 'Prävention';
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ use App\Form\FormSettings;
|
||||||
use App\Invoice\InvoiceSettings;
|
use App\Invoice\InvoiceSettings;
|
||||||
use App\Mailgateway\MailgatewaySettings;
|
use App\Mailgateway\MailgatewaySettings;
|
||||||
use App\Module\ModuleSettings;
|
use App\Module\ModuleSettings;
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class SettingServiceProvider extends ServiceProvider
|
class SettingServiceProvider extends ServiceProvider
|
||||||
|
@ -34,5 +35,6 @@ class SettingServiceProvider extends ServiceProvider
|
||||||
app(SettingFactory::class)->register(NamiSettings::class);
|
app(SettingFactory::class)->register(NamiSettings::class);
|
||||||
app(SettingFactory::class)->register(FormSettings::class);
|
app(SettingFactory::class)->register(FormSettings::class);
|
||||||
app(SettingFactory::class)->register(FileshareSettings::class);
|
app(SettingFactory::class)->register(FileshareSettings::class);
|
||||||
|
app(SettingFactory::class)->register(PreventionSettings::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace App\View\Mail;
|
||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
|
/** @todo replace content with EditorData */
|
||||||
class Editor extends Component
|
class Editor extends Component
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "7541aa772bfd34e379ec31ce8cefdb58",
|
"content-hash": "35a8a3ae207803d33e80b9daed8aa0fd",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "amphp/amp",
|
"name": "amphp/amp",
|
||||||
|
@ -463,16 +463,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/pipeline",
|
"name": "amphp/pipeline",
|
||||||
"version": "v1.2.0",
|
"version": "v1.2.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/amphp/pipeline.git",
|
"url": "https://github.com/amphp/pipeline.git",
|
||||||
"reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b"
|
"reference": "66c095673aa5b6e689e63b52d19e577459129ab3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/amphp/pipeline/zipball/f1c2ce35d27ae86ead018adb803eccca7421dd9b",
|
"url": "https://api.github.com/repos/amphp/pipeline/zipball/66c095673aa5b6e689e63b52d19e577459129ab3",
|
||||||
"reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b",
|
"reference": "66c095673aa5b6e689e63b52d19e577459129ab3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -518,7 +518,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/amphp/pipeline/issues",
|
"issues": "https://github.com/amphp/pipeline/issues",
|
||||||
"source": "https://github.com/amphp/pipeline/tree/v1.2.0"
|
"source": "https://github.com/amphp/pipeline/tree/v1.2.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -526,7 +526,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-10T14:48:16+00:00"
|
"time": "2024-07-04T00:56:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/process",
|
"name": "amphp/process",
|
||||||
|
@ -2454,16 +2454,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "giggsey/libphonenumber-for-php",
|
"name": "giggsey/libphonenumber-for-php",
|
||||||
"version": "8.13.39",
|
"version": "8.13.40",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
|
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
|
||||||
"reference": "5a36692616dba1ec4a24217f248021b1ec9cdade"
|
"reference": "795e0b760e5c439b6fa1ffa787c1d90c2face1ff"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/5a36692616dba1ec4a24217f248021b1ec9cdade",
|
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/795e0b760e5c439b6fa1ffa787c1d90c2face1ff",
|
||||||
"reference": "5a36692616dba1ec4a24217f248021b1ec9cdade",
|
"reference": "795e0b760e5c439b6fa1ffa787c1d90c2face1ff",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2525,7 +2525,7 @@
|
||||||
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
|
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
|
||||||
"source": "https://github.com/giggsey/libphonenumber-for-php"
|
"source": "https://github.com/giggsey/libphonenumber-for-php"
|
||||||
},
|
},
|
||||||
"time": "2024-06-14T12:43:12+00:00"
|
"time": "2024-07-01T11:38:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "giggsey/locale",
|
"name": "giggsey/locale",
|
||||||
|
@ -3468,16 +3468,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/horizon",
|
"name": "laravel/horizon",
|
||||||
"version": "v5.24.5",
|
"version": "v5.24.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/horizon.git",
|
"url": "https://github.com/laravel/horizon.git",
|
||||||
"reference": "3c359e3a9ebd3e3be012a15eedf2d64ef8b82540"
|
"reference": "e0fd80d9cc5f975455b3e46f5cc8e731a3eb6ea3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/3c359e3a9ebd3e3be012a15eedf2d64ef8b82540",
|
"url": "https://api.github.com/repos/laravel/horizon/zipball/e0fd80d9cc5f975455b3e46f5cc8e731a3eb6ea3",
|
||||||
"reference": "3c359e3a9ebd3e3be012a15eedf2d64ef8b82540",
|
"reference": "e0fd80d9cc5f975455b3e46f5cc8e731a3eb6ea3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -3541,9 +3541,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/laravel/horizon/issues",
|
"issues": "https://github.com/laravel/horizon/issues",
|
||||||
"source": "https://github.com/laravel/horizon/tree/v5.24.5"
|
"source": "https://github.com/laravel/horizon/tree/v5.24.6"
|
||||||
},
|
},
|
||||||
"time": "2024-05-31T16:18:41+00:00"
|
"time": "2024-06-25T21:23:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/passport",
|
"name": "laravel/passport",
|
||||||
|
@ -5382,16 +5382,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "meilisearch/meilisearch-php",
|
"name": "meilisearch/meilisearch-php",
|
||||||
"version": "v1.8.0",
|
"version": "v1.9.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/meilisearch/meilisearch-php.git",
|
"url": "https://github.com/meilisearch/meilisearch-php.git",
|
||||||
"reference": "77058e5cd0c9ee1236eaf8dfabdde2b339370b21"
|
"reference": "57f15d3cc13305c09d7d218720340b5f71157ae3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/77058e5cd0c9ee1236eaf8dfabdde2b339370b21",
|
"url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/57f15d3cc13305c09d7d218720340b5f71157ae3",
|
||||||
"reference": "77058e5cd0c9ee1236eaf8dfabdde2b339370b21",
|
"reference": "57f15d3cc13305c09d7d218720340b5f71157ae3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -5406,7 +5406,7 @@
|
||||||
"guzzlehttp/guzzle": "^7.1",
|
"guzzlehttp/guzzle": "^7.1",
|
||||||
"http-interop/http-factory-guzzle": "^1.0",
|
"http-interop/http-factory-guzzle": "^1.0",
|
||||||
"phpstan/extension-installer": "^1.1",
|
"phpstan/extension-installer": "^1.1",
|
||||||
"phpstan/phpstan": "1.10.67",
|
"phpstan/phpstan": "1.11.5",
|
||||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||||
"phpstan/phpstan-phpunit": "^1.0",
|
"phpstan/phpstan-phpunit": "^1.0",
|
||||||
"phpstan/phpstan-strict-rules": "^1.1",
|
"phpstan/phpstan-strict-rules": "^1.1",
|
||||||
|
@ -5444,9 +5444,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/meilisearch/meilisearch-php/issues",
|
"issues": "https://github.com/meilisearch/meilisearch-php/issues",
|
||||||
"source": "https://github.com/meilisearch/meilisearch-php/tree/v1.8.0"
|
"source": "https://github.com/meilisearch/meilisearch-php/tree/v1.9.0"
|
||||||
},
|
},
|
||||||
"time": "2024-05-06T13:58:08+00:00"
|
"time": "2024-07-01T11:36:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monicahq/laravel-sabre",
|
"name": "monicahq/laravel-sabre",
|
||||||
|
@ -5941,16 +5941,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nikic/php-parser",
|
"name": "nikic/php-parser",
|
||||||
"version": "v5.0.2",
|
"version": "v5.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
|
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -5961,7 +5961,7 @@
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"ircmaxell/php-yacc": "^0.0.7",
|
"ircmaxell/php-yacc": "^0.0.7",
|
||||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
"phpunit/phpunit": "^9.0"
|
||||||
},
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
"bin/php-parse"
|
"bin/php-parse"
|
||||||
|
@ -5993,9 +5993,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
|
"source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0"
|
||||||
},
|
},
|
||||||
"time": "2024-03-05T20:51:40+00:00"
|
"time": "2024-07-01T20:03:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nunomaduro/collision",
|
"name": "nunomaduro/collision",
|
||||||
|
@ -9173,16 +9173,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sabre/vobject",
|
"name": "sabre/vobject",
|
||||||
"version": "4.5.4",
|
"version": "4.5.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sabre-io/vobject.git",
|
"url": "https://github.com/sabre-io/vobject.git",
|
||||||
"reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772"
|
"reference": "7148cf57d25aaba0a49f6656d37c35e8175b3087"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772",
|
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/7148cf57d25aaba0a49f6656d37c35e8175b3087",
|
||||||
"reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772",
|
"reference": "7148cf57d25aaba0a49f6656d37c35e8175b3087",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -9273,7 +9273,7 @@
|
||||||
"issues": "https://github.com/sabre-io/vobject/issues",
|
"issues": "https://github.com/sabre-io/vobject/issues",
|
||||||
"source": "https://github.com/fruux/sabre-vobject"
|
"source": "https://github.com/fruux/sabre-vobject"
|
||||||
},
|
},
|
||||||
"time": "2023-11-09T12:54:37+00:00"
|
"time": "2024-07-02T08:48:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sabre/xml",
|
"name": "sabre/xml",
|
||||||
|
@ -15154,6 +15154,134 @@
|
||||||
},
|
},
|
||||||
"time": "2024-05-20T23:03:51+00:00"
|
"time": "2024-05-20T23:03:51+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "php-di/invoker",
|
||||||
|
"version": "2.3.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHP-DI/Invoker.git",
|
||||||
|
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||||
|
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.3",
|
||||||
|
"psr/container": "^1.0|^2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"athletic/athletic": "~0.1.8",
|
||||||
|
"mnapoli/hard-mode": "~0.3.0",
|
||||||
|
"phpunit/phpunit": "^9.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Invoker\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Generic and extensible callable invoker",
|
||||||
|
"homepage": "https://github.com/PHP-DI/Invoker",
|
||||||
|
"keywords": [
|
||||||
|
"callable",
|
||||||
|
"dependency",
|
||||||
|
"dependency-injection",
|
||||||
|
"injection",
|
||||||
|
"invoke",
|
||||||
|
"invoker"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHP-DI/Invoker/issues",
|
||||||
|
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.4"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/mnapoli",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-09-08T09:24:21+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "php-di/php-di",
|
||||||
|
"version": "7.0.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHP-DI/PHP-DI.git",
|
||||||
|
"reference": "8097948a89f6ec782839b3e958432f427cac37fd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/8097948a89f6ec782839b3e958432f427cac37fd",
|
||||||
|
"reference": "8097948a89f6ec782839b3e958432f427cac37fd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"laravel/serializable-closure": "^1.0",
|
||||||
|
"php": ">=8.0",
|
||||||
|
"php-di/invoker": "^2.0",
|
||||||
|
"psr/container": "^1.1 || ^2.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/container-implementation": "^1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3",
|
||||||
|
"friendsofphp/proxy-manager-lts": "^1",
|
||||||
|
"mnapoli/phpunit-easymock": "^1.3",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"vimeo/psalm": "^4.6"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"DI\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "The dependency injection container for humans",
|
||||||
|
"homepage": "https://php-di.org/",
|
||||||
|
"keywords": [
|
||||||
|
"PSR-11",
|
||||||
|
"container",
|
||||||
|
"container-interop",
|
||||||
|
"dependency injection",
|
||||||
|
"di",
|
||||||
|
"ioc",
|
||||||
|
"psr11"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHP-DI/PHP-DI/issues",
|
||||||
|
"source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.6"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/mnapoli",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/php-di/php-di",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-11-02T10:04:50+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "phpmyadmin/sql-parser",
|
"name": "phpmyadmin/sql-parser",
|
||||||
"version": "5.9.0",
|
"version": "5.9.0",
|
||||||
|
@ -15244,16 +15372,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.11.5",
|
"version": "1.11.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "490f0ae1c92b082f154681d7849aee776a7c1443"
|
"reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/490f0ae1c92b082f154681d7849aee776a7c1443",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6ac78f1165346c83b4a753f7e4186d969c6ad0ee",
|
||||||
"reference": "490f0ae1c92b082f154681d7849aee776a7c1443",
|
"reference": "6ac78f1165346c83b4a753f7e4186d969c6ad0ee",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -15298,7 +15426,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-06-17T15:10:54+00:00"
|
"time": "2024-07-01T15:33:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-mockery",
|
"name": "phpstan/phpstan-mockery",
|
||||||
|
@ -15350,71 +15478,18 @@
|
||||||
},
|
},
|
||||||
"time": "2024-01-10T13:50:05+00:00"
|
"time": "2024-01-10T13:50:05+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "pimple/pimple",
|
|
||||||
"version": "v3.5.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/silexphp/Pimple.git",
|
|
||||||
"reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
|
|
||||||
"reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.2.5",
|
|
||||||
"psr/container": "^1.1 || ^2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/phpunit-bridge": "^5.4@dev"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.4.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": {
|
|
||||||
"Pimple": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Pimple, a simple Dependency Injection Container",
|
|
||||||
"homepage": "https://pimple.symfony.com",
|
|
||||||
"keywords": [
|
|
||||||
"container",
|
|
||||||
"dependency injection"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/silexphp/Pimple/tree/v3.5.0"
|
|
||||||
},
|
|
||||||
"time": "2021-10-28T11:13:42+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
"version": "1.1.1",
|
"version": "1.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rectorphp/rector.git",
|
"url": "https://github.com/rectorphp/rector.git",
|
||||||
"reference": "c930cdb21294f10955ddfc31b720971e8333943d"
|
"reference": "2fa387553db22b6f9bcccf5ff16f2c2c18a52a65"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/c930cdb21294f10955ddfc31b720971e8333943d",
|
"url": "https://api.github.com/repos/rectorphp/rector/zipball/2fa387553db22b6f9bcccf5ff16f2c2c18a52a65",
|
||||||
"reference": "c930cdb21294f10955ddfc31b720971e8333943d",
|
"reference": "2fa387553db22b6f9bcccf5ff16f2c2c18a52a65",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -15452,7 +15527,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/rectorphp/rector/issues",
|
"issues": "https://github.com/rectorphp/rector/issues",
|
||||||
"source": "https://github.com/rectorphp/rector/tree/1.1.1"
|
"source": "https://github.com/rectorphp/rector/tree/1.2.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -15460,20 +15535,20 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-06-21T07:51:17+00:00"
|
"time": "2024-07-01T14:24:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/laravel-ray",
|
"name": "spatie/laravel-ray",
|
||||||
"version": "1.36.2",
|
"version": "1.37.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/laravel-ray.git",
|
"url": "https://github.com/spatie/laravel-ray.git",
|
||||||
"reference": "1852faa96e5aa6778ea3401ec3176eee77268718"
|
"reference": "f57b294a3815be37effa9d13f54f2fbe5a2fff37"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/laravel-ray/zipball/1852faa96e5aa6778ea3401ec3176eee77268718",
|
"url": "https://api.github.com/repos/spatie/laravel-ray/zipball/f57b294a3815be37effa9d13f54f2fbe5a2fff37",
|
||||||
"reference": "1852faa96e5aa6778ea3401ec3176eee77268718",
|
"reference": "f57b294a3815be37effa9d13f54f2fbe5a2fff37",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -15487,7 +15562,7 @@
|
||||||
"spatie/backtrace": "^1.0",
|
"spatie/backtrace": "^1.0",
|
||||||
"spatie/ray": "^1.41.1",
|
"spatie/ray": "^1.41.1",
|
||||||
"symfony/stopwatch": "4.2|^5.1|^6.0|^7.0",
|
"symfony/stopwatch": "4.2|^5.1|^6.0|^7.0",
|
||||||
"zbateson/mail-mime-parser": "^1.3.1|^2.0"
|
"zbateson/mail-mime-parser": "^1.3.1|^2.0|^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"guzzlehttp/guzzle": "^7.3",
|
"guzzlehttp/guzzle": "^7.3",
|
||||||
|
@ -15535,7 +15610,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/spatie/laravel-ray/issues",
|
"issues": "https://github.com/spatie/laravel-ray/issues",
|
||||||
"source": "https://github.com/spatie/laravel-ray/tree/1.36.2"
|
"source": "https://github.com/spatie/laravel-ray/tree/1.37.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -15547,7 +15622,7 @@
|
||||||
"type": "other"
|
"type": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-05-02T08:26:02+00:00"
|
"time": "2024-07-03T08:48:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/macroable",
|
"name": "spatie/macroable",
|
||||||
|
@ -15900,30 +15975,31 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "zbateson/mail-mime-parser",
|
"name": "zbateson/mail-mime-parser",
|
||||||
"version": "2.4.1",
|
"version": "3.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/zbateson/mail-mime-parser.git",
|
"url": "https://github.com/zbateson/mail-mime-parser.git",
|
||||||
"reference": "ff49e02f6489b38f7cc3d1bd3971adc0f872569c"
|
"reference": "6ade63b0a43047935791d7977e22717a68cc388b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/ff49e02f6489b38f7cc3d1bd3971adc0f872569c",
|
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/6ade63b0a43047935791d7977e22717a68cc388b",
|
||||||
"reference": "ff49e02f6489b38f7cc3d1bd3971adc0f872569c",
|
"reference": "6ade63b0a43047935791d7977e22717a68cc388b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"guzzlehttp/psr7": "^1.7.0|^2.0",
|
"guzzlehttp/psr7": "^2.5",
|
||||||
"php": ">=7.1",
|
"php": ">=8.0",
|
||||||
"pimple/pimple": "^3.0",
|
"php-di/php-di": "^6.0|^7.0",
|
||||||
"zbateson/mb-wrapper": "^1.0.1",
|
"psr/log": "^1|^2|^3",
|
||||||
"zbateson/stream-decorators": "^1.0.6"
|
"zbateson/mb-wrapper": "^2.0",
|
||||||
|
"zbateson/stream-decorators": "^2.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "*",
|
"friendsofphp/php-cs-fixer": "*",
|
||||||
"mikey179/vfsstream": "^1.6.0",
|
"monolog/monolog": "^2|^3",
|
||||||
"phpstan/phpstan": "*",
|
"phpstan/phpstan": "*",
|
||||||
"phpunit/phpunit": "<10"
|
"phpunit/phpunit": "^9.6"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-iconv": "For best support/performance",
|
"ext-iconv": "For best support/performance",
|
||||||
|
@ -15971,24 +16047,24 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-04-28T00:58:54+00:00"
|
"time": "2024-04-29T21:53:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "zbateson/mb-wrapper",
|
"name": "zbateson/mb-wrapper",
|
||||||
"version": "1.2.1",
|
"version": "2.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/zbateson/mb-wrapper.git",
|
"url": "https://github.com/zbateson/mb-wrapper.git",
|
||||||
"reference": "09a8b77eb94af3823a9a6623dcc94f8d988da67f"
|
"reference": "9e4373a153585d12b6c621ac4a6bb143264d4619"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/09a8b77eb94af3823a9a6623dcc94f8d988da67f",
|
"url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/9e4373a153585d12b6c621ac4a6bb143264d4619",
|
||||||
"reference": "09a8b77eb94af3823a9a6623dcc94f8d988da67f",
|
"reference": "9e4373a153585d12b6c621ac4a6bb143264d4619",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1",
|
"php": ">=8.0",
|
||||||
"symfony/polyfill-iconv": "^1.9",
|
"symfony/polyfill-iconv": "^1.9",
|
||||||
"symfony/polyfill-mbstring": "^1.9"
|
"symfony/polyfill-mbstring": "^1.9"
|
||||||
},
|
},
|
||||||
|
@ -16032,7 +16108,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/zbateson/mb-wrapper/issues",
|
"issues": "https://github.com/zbateson/mb-wrapper/issues",
|
||||||
"source": "https://github.com/zbateson/mb-wrapper/tree/1.2.1"
|
"source": "https://github.com/zbateson/mb-wrapper/tree/2.0.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -16040,31 +16116,31 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-18T04:31:04+00:00"
|
"time": "2024-03-20T01:38:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "zbateson/stream-decorators",
|
"name": "zbateson/stream-decorators",
|
||||||
"version": "1.2.1",
|
"version": "2.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/zbateson/stream-decorators.git",
|
"url": "https://github.com/zbateson/stream-decorators.git",
|
||||||
"reference": "783b034024fda8eafa19675fb2552f8654d3a3e9"
|
"reference": "32a2a62fb0f26313395c996ebd658d33c3f9c4e5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/783b034024fda8eafa19675fb2552f8654d3a3e9",
|
"url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/32a2a62fb0f26313395c996ebd658d33c3f9c4e5",
|
||||||
"reference": "783b034024fda8eafa19675fb2552f8654d3a3e9",
|
"reference": "32a2a62fb0f26313395c996ebd658d33c3f9c4e5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"guzzlehttp/psr7": "^1.9 | ^2.0",
|
"guzzlehttp/psr7": "^2.5",
|
||||||
"php": ">=7.2",
|
"php": ">=8.0",
|
||||||
"zbateson/mb-wrapper": "^1.0.0"
|
"zbateson/mb-wrapper": "^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "*",
|
"friendsofphp/php-cs-fixer": "*",
|
||||||
"phpstan/phpstan": "*",
|
"phpstan/phpstan": "*",
|
||||||
"phpunit/phpunit": "<10.0"
|
"phpunit/phpunit": "^9.6|^10.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -16095,7 +16171,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/zbateson/stream-decorators/issues",
|
"issues": "https://github.com/zbateson/stream-decorators/issues",
|
||||||
"source": "https://github.com/zbateson/stream-decorators/tree/1.2.1"
|
"source": "https://github.com/zbateson/stream-decorators/tree/2.1.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -16103,7 +16179,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-05-30T22:51:52+00:00"
|
"time": "2024-04-29T21:42:39+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [
|
"aliases": [
|
||||||
|
@ -16134,9 +16210,9 @@
|
||||||
],
|
],
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
|
"league/flysystem-webdav": 20,
|
||||||
"zoomyboy/laravel-nami": 20,
|
"zoomyboy/laravel-nami": 20,
|
||||||
"zoomyboy/medialibrary-helper": 20,
|
"zoomyboy/medialibrary-helper": 20,
|
||||||
"league/flysystem-webdav": 20,
|
|
||||||
"zoomyboy/table-document": 20,
|
"zoomyboy/table-document": 20,
|
||||||
"zoomyboy/tex": 20
|
"zoomyboy/tex": 20
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
|
use App\Lib\Editor\EditorDataSettingsCast;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each settings class used in your application must be registered, you can
|
* Each settings class used in your application must be registered, you can
|
||||||
* put them (manually) here.
|
* put them (manually) here.
|
||||||
*/
|
*/
|
||||||
'settings' => [
|
'settings' => [],
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In these directories settings migrations will be stored and ran when migrating. A settings
|
* In these directories settings migrations will be stored and ran when migrating. A settings
|
||||||
|
@ -60,7 +61,7 @@ return [
|
||||||
'global_casts' => [
|
'global_casts' => [
|
||||||
DateTimeInterface::class => Spatie\LaravelSettings\SettingsCasts\DateTimeInterfaceCast::class,
|
DateTimeInterface::class => Spatie\LaravelSettings\SettingsCasts\DateTimeInterfaceCast::class,
|
||||||
DateTimeZone::class => Spatie\LaravelSettings\SettingsCasts\DateTimeZoneCast::class,
|
DateTimeZone::class => Spatie\LaravelSettings\SettingsCasts\DateTimeZoneCast::class,
|
||||||
Spatie\DataTransferObject\DataTransferObject::class => Spatie\LaravelSettings\SettingsCasts\DtoCast::class,
|
Spatie\LaravelData\Data::class => Spatie\LaravelSettings\SettingsCasts\DataCast::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Form\Models\Participant;
|
||||||
|
use App\Member\Member;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('participants', function (Blueprint $table) {
|
||||||
|
$table->datetime('last_remembered_at')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('forms', function (Blueprint $table) {
|
||||||
|
$table->boolean('needs_prevention')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('forms', function (Blueprint $table) {
|
||||||
|
$table->json('prevention_text')->after('description')->default(json_encode(EditorRequestFactory::new()->empty()->create()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('forms', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('prevention_text');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||||
|
|
||||||
|
return new class extends SettingsMigration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->migrator->add('prevention.formmail', ['time' => 1, 'blocks' => [], 'version' => '1.0']);
|
||||||
|
}
|
||||||
|
};
|
56
phpstan.neon
56
phpstan.neon
|
@ -6,6 +6,7 @@ parameters:
|
||||||
|
|
||||||
stubFiles:
|
stubFiles:
|
||||||
- tests/stub/phpstan/TestResponse.stub
|
- tests/stub/phpstan/TestResponse.stub
|
||||||
|
- tests/stub/phpstan/Settings.stub
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
- app
|
- app
|
||||||
|
@ -33,61 +34,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: app/Activity.php
|
path: app/Activity.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\AddressBookBackend\\:\\:getMultipleCards\\(\\) has parameter \\$uris with no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/AddressBookBackend.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\AddressBookBackend\\:\\:getMultipleCards\\(\\) return type has no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/AddressBookBackend.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:getGroupMemberSet\\(\\) return type has no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:getGroupMemberSet\\(\\) should return array but return statement is missing\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:getGroupMembership\\(\\) return type has no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:getGroupMembership\\(\\) should return array but returns null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:setGroupMemberSet\\(\\) has no return type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\Principal\\:\\:setGroupMemberSet\\(\\) has parameter \\$members with no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/Principal.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method App\\\\Dav\\\\ServiceProvider\\:\\:plugins\\(\\) return type has no value type specified in iterable type array\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Dav/ServiceProvider.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^PHPDoc type array\\<string\\> of property App\\\\Exceptions\\\\Handler\\:\\:\\$dontFlash is not covariant with PHPDoc type array\\<int, string\\> of overridden property Illuminate\\\\Foundation\\\\Exceptions\\\\Handler\\:\\:\\$dontFlash\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Exceptions/Handler.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^PHPDoc type array\\<string\\> of property App\\\\Exceptions\\\\Handler\\:\\:\\$dontReport is not covariant with PHPDoc type array\\<int, class\\-string\\<Throwable\\>\\> of overridden property Illuminate\\\\Foundation\\\\Exceptions\\\\Handler\\:\\:\\$dontReport\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: app/Exceptions/Handler.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method App\\\\Http\\\\Controllers\\\\Auth\\\\RegisterController\\:\\:create\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
|
message: "#^Method App\\\\Http\\\\Controllers\\\\Auth\\\\RegisterController\\:\\:create\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
@ -115,6 +115,16 @@
|
||||||
<f-select id="to_group_field" v-model="single.export.to_group_field" :options="allFields" label="Nach Gruppe schreiben" name="to_group_field"></f-select>
|
<f-select id="to_group_field" v-model="single.export.to_group_field" :options="allFields" label="Nach Gruppe schreiben" name="to_group_field"></f-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-show="active === 4" class="grid grid-cols-2 gap-3">
|
||||||
|
<f-switch id="needs_prevention" v-model="single.needs_prevention" name="needs_prevention" label="Prävention"></f-switch>
|
||||||
|
<f-editor
|
||||||
|
id="prevention_text"
|
||||||
|
v-model="single.prevention_text"
|
||||||
|
hint="Wird an die Präventions-Email angehangen, die Teilnehmende dieser Veranstaltung erhalten"
|
||||||
|
:rows="6"
|
||||||
|
label="Präventions-Hinweis"
|
||||||
|
></f-editor>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a href="#" @click.prevent="submit">
|
<a href="#" @click.prevent="submit">
|
||||||
|
@ -191,7 +201,7 @@ const deleting = ref(null);
|
||||||
const showing = ref(null);
|
const showing = ref(null);
|
||||||
const fileSettingPopup = ref(null);
|
const fileSettingPopup = ref(null);
|
||||||
|
|
||||||
const tabs = [{ title: 'Allgemeines' }, { title: 'Formular' }, { title: 'Bestätigungs-E-Mail' }, { title: 'Export' }];
|
const tabs = [{ title: 'Allgemeines' }, { title: 'Formular' }, { title: 'Bestätigungs-E-Mail' }, { title: 'Export' }, { title: 'Prävention' }];
|
||||||
const mailTabs = [{ title: 'vor Daten' }, { title: 'nach Daten' }];
|
const mailTabs = [{ title: 'vor Daten' }, { title: 'nach Daten' }];
|
||||||
|
|
||||||
const allFields = computed(() => {
|
const allFields = computed(() => {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<page-layout>
|
||||||
|
<template #right>
|
||||||
|
<f-save-button form="preventionform"></f-save-button>
|
||||||
|
</template>
|
||||||
|
<setting-layout v-if="loaded">
|
||||||
|
<form id="preventionform" class="grow p-6" @submit.prevent="submit">
|
||||||
|
<div class="col-span-full text-gray-100 mb-3">
|
||||||
|
<p class="text-sm">Hier kannst du Einstellungen zu Prävention setzen.</p>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-4 mt-2">
|
||||||
|
<f-editor id="frommail" v-model="data.formmail" label="E-Mail für Veranstaltungs-TN"></f-editor>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</setting-layout>
|
||||||
|
</page-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="js" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useApiIndex } from '../../composables/useApiIndex.js';
|
||||||
|
import SettingLayout from '../setting/Layout.vue';
|
||||||
|
|
||||||
|
const { axios, data, reload } = useApiIndex('/api/prevention', 'prevention');
|
||||||
|
const loaded = ref(false);
|
||||||
|
|
||||||
|
async function load() {
|
||||||
|
await reload();
|
||||||
|
loaded.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
await axios.post('/api/prevention', { ...data.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
load();
|
||||||
|
</script>
|
|
@ -0,0 +1,13 @@
|
||||||
|
@component('mail::message')
|
||||||
|
# Hallo {{ $preventable->member->fullname }},
|
||||||
|
|
||||||
|
<x-mail-view::editor :content="$bodyText->toArray()['blocks']"></x-mail-view::editor>
|
||||||
|
|
||||||
|
@component('mail::subcopy')
|
||||||
|
|
||||||
|
Herzliche Grüße und gut Pfad
|
||||||
|
|
||||||
|
{{$settings->from_long}}
|
||||||
|
@endcomponent
|
||||||
|
|
||||||
|
@endcomponent
|
|
@ -3,9 +3,13 @@
|
||||||
use App\Contribution\Actions\GenerateApiAction as ContributionGenerateApiAction;
|
use App\Contribution\Actions\GenerateApiAction as ContributionGenerateApiAction;
|
||||||
use App\Form\Actions\FormApiListAction;
|
use App\Form\Actions\FormApiListAction;
|
||||||
use App\Form\Actions\RegisterAction;
|
use App\Form\Actions\RegisterAction;
|
||||||
|
use App\Prevention\Actions\SettingStoreAction as PreventionStoreAction;
|
||||||
use App\Group\Actions\GroupApiIndexAction;
|
use App\Group\Actions\GroupApiIndexAction;
|
||||||
|
use App\Prevention\Actions\SettingApiAction;
|
||||||
|
|
||||||
Route::post('/contribution-generate', ContributionGenerateApiAction::class)->name('api.contribution.generate')->middleware('client:contribution-generate');
|
Route::post('/contribution-generate', ContributionGenerateApiAction::class)->name('api.contribution.generate')->middleware('client:contribution-generate');
|
||||||
Route::post('/form/{form}/register', RegisterAction::class)->name('form.register');
|
Route::post('/form/{form}/register', RegisterAction::class)->name('form.register');
|
||||||
Route::get('/group/{group?}', GroupApiIndexAction::class)->name('api.group');
|
Route::get('/group/{group?}', GroupApiIndexAction::class)->name('api.group');
|
||||||
Route::get('/form', FormApiListAction::class)->name('api.form.index');
|
Route::get('/form', FormApiListAction::class)->name('api.form.index');
|
||||||
|
Route::get('/prevention', SettingApiAction::class)->name('api.prevention.index');
|
||||||
|
Route::post('/prevention', PreventionStoreAction::class)->name('api.prevention.store');
|
||||||
|
|
|
@ -52,6 +52,7 @@ class FormIndexActionTest extends FormTestCase
|
||||||
->assertInertiaPath('data.data.0.is_active', true)
|
->assertInertiaPath('data.data.0.is_active', true)
|
||||||
->assertInertiaPath('data.data.0.is_private', false)
|
->assertInertiaPath('data.data.0.is_private', false)
|
||||||
->assertInertiaPath('data.data.0.registration_from', '2023-05-06 04:00:00')
|
->assertInertiaPath('data.data.0.registration_from', '2023-05-06 04:00:00')
|
||||||
|
->assertInertiaPath('data.data.0.needs_prevention', false)
|
||||||
->assertInertiaPath('data.data.0.registration_until', '2023-04-01 05:00:00')
|
->assertInertiaPath('data.data.0.registration_until', '2023-04-01 05:00:00')
|
||||||
->assertInertiaPath('data.data.0.links.participant_index', route('form.participant.index', ['form' => $form]))
|
->assertInertiaPath('data.data.0.links.participant_index', route('form.participant.index', ['form' => $form]))
|
||||||
->assertInertiaPath('data.data.0.links.export', route('form.export', ['form' => $form]))
|
->assertInertiaPath('data.data.0.links.export', route('form.export', ['form' => $form]))
|
||||||
|
@ -60,6 +61,7 @@ class FormIndexActionTest extends FormTestCase
|
||||||
->assertInertiaPath('data.meta.templates.0.name', 'tname')
|
->assertInertiaPath('data.meta.templates.0.name', 'tname')
|
||||||
->assertInertiaPath('data.meta.templates.0.config.sections.0.name', 'sname')
|
->assertInertiaPath('data.meta.templates.0.config.sections.0.name', 'sname')
|
||||||
->assertInertiaPath('data.meta.default.name', '')
|
->assertInertiaPath('data.meta.default.name', '')
|
||||||
|
->assertInertiaPath('data.meta.default.prevention_text.version', '1.0')
|
||||||
->assertInertiaPath('data.meta.default.description', [])
|
->assertInertiaPath('data.meta.default.description', [])
|
||||||
->assertInertiaPath('data.meta.default.excerpt', '')
|
->assertInertiaPath('data.meta.default.excerpt', '')
|
||||||
->assertInertiaPath('data.meta.default.is_active', true)
|
->assertInertiaPath('data.meta.default.is_active', true)
|
||||||
|
|
|
@ -21,6 +21,7 @@ use Worksome\RequestFactories\RequestFactory;
|
||||||
* @method self isActive(bool $isActive)
|
* @method self isActive(bool $isActive)
|
||||||
* @method self isPrivate(bool $isPrivate)
|
* @method self isPrivate(bool $isPrivate)
|
||||||
* @method self export(ExportData $export)
|
* @method self export(ExportData $export)
|
||||||
|
* @method self preventionText(EditorRequestFactory $text)
|
||||||
*/
|
*/
|
||||||
class FormRequest extends RequestFactory
|
class FormRequest extends RequestFactory
|
||||||
{
|
{
|
||||||
|
@ -49,6 +50,8 @@ class FormRequest extends RequestFactory
|
||||||
'header_image' => $this->getHeaderImagePayload(str()->uuid() . '.jpg'),
|
'header_image' => $this->getHeaderImagePayload(str()->uuid() . '.jpg'),
|
||||||
'mailattachments' => [],
|
'mailattachments' => [],
|
||||||
'export' => ExportData::from([])->toArray(),
|
'export' => ExportData::from([])->toArray(),
|
||||||
|
'needs_prevention' => $this->faker->boolean(),
|
||||||
|
'prevention_text' => EditorRequestFactory::new()->create(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ class FormStoreActionTest extends FormTestCase
|
||||||
->name('formname')
|
->name('formname')
|
||||||
->description($description)
|
->description($description)
|
||||||
->excerpt('avff')
|
->excerpt('avff')
|
||||||
|
->preventionText(EditorRequestFactory::new()->paragraphs(['lorem ipsum']))
|
||||||
->registrationFrom('2023-05-04 01:00:00')->registrationUntil('2023-07-07 01:00:00')->from('2023-07-07')->to('2023-07-08')
|
->registrationFrom('2023-05-04 01:00:00')->registrationUntil('2023-07-07 01:00:00')->from('2023-07-07')->to('2023-07-08')
|
||||||
->mailTop(EditorRequestFactory::new()->text(11, 'lala'))
|
->mailTop(EditorRequestFactory::new()->text(11, 'lala'))
|
||||||
->mailBottom(EditorRequestFactory::new()->text(12, 'lalab'))
|
->mailBottom(EditorRequestFactory::new()->text(12, 'lalab'))
|
||||||
|
@ -38,6 +39,7 @@ class FormStoreActionTest extends FormTestCase
|
||||||
$form = Form::latest()->first();
|
$form = Form::latest()->first();
|
||||||
$this->assertEquals('sname', $form->config->sections->get(0)->name);
|
$this->assertEquals('sname', $form->config->sections->get(0)->name);
|
||||||
$this->assertEquals('formname', $form->name);
|
$this->assertEquals('formname', $form->name);
|
||||||
|
$this->assertEquals('lorem ipsum', $form->prevention_text->blocks[0]['data']['text']);
|
||||||
$this->assertEquals('avff', $form->excerpt);
|
$this->assertEquals('avff', $form->excerpt);
|
||||||
$this->assertEquals($description->paragraphBlock(10, 'Lorem'), $form->description);
|
$this->assertEquals($description->paragraphBlock(10, 'Lorem'), $form->description);
|
||||||
$this->assertEquals(json_decode('{"time":1,"blocks":[{"id":11,"type":"paragraph","data":{"text":"lala"},"tunes":{"condition":{"mode":"all","ifs":[]}}}],"version":"1.0"}', true), $form->mail_top);
|
$this->assertEquals(json_decode('{"time":1,"blocks":[{"id":11,"type":"paragraph","data":{"text":"lala"},"tunes":{"condition":{"mode":"all","ifs":[]}}}],"version":"1.0"}', true), $form->mail_top);
|
||||||
|
@ -88,6 +90,7 @@ class FormStoreActionTest extends FormTestCase
|
||||||
yield [FormRequest::new()->state(['header_image' => null]), ['header_image' => 'Bild ist erforderlich']];
|
yield [FormRequest::new()->state(['header_image' => null]), ['header_image' => 'Bild ist erforderlich']];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider validationDataProvider
|
* @dataProvider validationDataProvider
|
||||||
* @param array<string, string> $messages
|
* @param array<string, string> $messages
|
||||||
|
|
|
@ -5,8 +5,9 @@ namespace Tests\Feature\Form;
|
||||||
use App\Fileshare\Data\FileshareResourceData;
|
use App\Fileshare\Data\FileshareResourceData;
|
||||||
use App\Form\Data\ExportData;
|
use App\Form\Data\ExportData;
|
||||||
use App\Form\Models\Form;
|
use App\Form\Models\Form;
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
|
||||||
class FormUpdateActionTest extends FormTestCase
|
class FormUpdateActionTest extends FormTestCase
|
||||||
{
|
{
|
||||||
|
@ -124,4 +125,18 @@ class FormUpdateActionTest extends FormTestCase
|
||||||
$this->patchJson(route('form.update', ['form' => $form]), $payload)->assertSessionDoesntHaveErrors()->assertOk();
|
$this->patchJson(route('form.update', ['form' => $form]), $payload)->assertSessionDoesntHaveErrors()->assertOk();
|
||||||
$this->assertEquals(['firstname', 'geb', 'lastname'], $form->fresh()->meta['active_columns']);
|
$this->assertEquals(['firstname', 'geb', 'lastname'], $form->fresh()->meta['active_columns']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItUpdatesPrevention(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami()->withoutExceptionHandling();
|
||||||
|
$form = Form::factory()->create();
|
||||||
|
$payload = FormRequest::new()
|
||||||
|
->preventionText(EditorRequestFactory::new()->text(10, 'lorem ipsum'))
|
||||||
|
->state(['needs_prevention' => true])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$this->patchJson(route('form.update', ['form' => $form]), $payload);
|
||||||
|
$this->assertTrue($form->fresh()->needs_prevention);
|
||||||
|
$this->assertEquals('lorem ipsum', $form->fresh()->prevention_text->blocks[0]['data']['text']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,264 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Member;
|
||||||
|
|
||||||
|
use App\Prevention\Enums\Prevention;
|
||||||
|
use App\Form\Actions\PreventionRememberAction;
|
||||||
|
use App\Form\Enums\NamiType;
|
||||||
|
use App\Form\Enums\SpecialType;
|
||||||
|
use App\Form\Models\Form;
|
||||||
|
use App\Form\Models\Participant;
|
||||||
|
use App\Invoice\InvoiceSettings;
|
||||||
|
use App\Prevention\Mails\PreventionRememberMail;
|
||||||
|
use App\Member\Member;
|
||||||
|
use App\Member\Membership;
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
|
use Generator;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Tests\Lib\CreatesFormFields;
|
||||||
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class PreventionTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
use DatabaseTransactions;
|
||||||
|
use CreatesFormFields;
|
||||||
|
|
||||||
|
public function testItRemembersWhenNotRememberedYet(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertEquals(now()->format('Y-m-d'), $participant->fresh()->last_remembered_at->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItRemembersWhenRememberIsDue(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = tap($this->createParticipant($form), fn ($p) => $p->update(['last_remembered_at' => now()->subWeeks(3)]));
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertEquals(now()->format('Y-m-d'), $participant->fresh()->last_remembered_at->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntRememberWhenRememberingIsNotDue(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = tap($this->createParticipant($form), fn ($p) => $p->update(['last_remembered_at' => now()->subWeeks(1)]));
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertEquals(now()->subWeeks(1)->format('Y-m-d'), $participant->fresh()->last_remembered_at->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntRememberWhenFormDoesntNeedPrevention(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = tap($this->createForm(), fn ($form) => $form->update(['needs_prevention' => false]));
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertNull($participant->fresh()->last_remembered_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntRememberWhenParticipantDoesntHaveMember(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
$participant->member->delete();
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertNull($participant->fresh()->last_remembered_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntRememberWhenMemberIsNotALeader(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
$participant->member->memberships->each->delete();
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
$this->assertNull($participant->fresh()->last_remembered_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function attributes(): Generator
|
||||||
|
{
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => null, 'ps_at' => now()],
|
||||||
|
'preventions' => [Prevention::EFZ]
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now(), 'ps_at' => null],
|
||||||
|
'preventions' => [Prevention::PS]
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now()->subDay(), 'ps_at' => now()],
|
||||||
|
'preventions' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now(), 'ps_at' => now()->subDay()],
|
||||||
|
'preventions' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now()->subYears(5)->subDay(), 'ps_at' => now()],
|
||||||
|
'preventions' => [Prevention::EFZ]
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now(), 'ps_at' => now()->subYears(5)->subDay()],
|
||||||
|
'preventions' => [Prevention::PS]
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now(), 'ps_at' => now()->subYears(5)->subDay(), 'more_ps_at' => now()],
|
||||||
|
'preventions' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
'attrs' => ['efz' => now(), 'ps_at' => now()->subYears(15), 'more_ps_at' => now()->subYears(5)->subDay()],
|
||||||
|
'preventions' => [Prevention::MOREPS],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, Prevention> $preventions
|
||||||
|
* @param array<string, mixed> $memberAttributes
|
||||||
|
* @dataProvider attributes
|
||||||
|
*/
|
||||||
|
public function testItRemembersMember(array $memberAttributes, array $preventions): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
$participant->member->update($memberAttributes);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
if (count($preventions)) {
|
||||||
|
Mail::assertSent(PreventionRememberMail::class, fn ($mail) => $mail->preventable->preventions() === $preventions);
|
||||||
|
$this->assertNotNull($participant->fresh()->last_remembered_at);
|
||||||
|
} else {
|
||||||
|
Mail::assertNotSent(PreventionRememberMail::class);
|
||||||
|
$this->assertNull($participant->fresh()->last_remembered_at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntRememberParticipantThatHasNoMail(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
$participant->update(['data' => [...$participant->data, 'email' => '']]);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
Mail::assertNotSent(PreventionRememberMail::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItRendersMail(): void
|
||||||
|
{
|
||||||
|
InvoiceSettings::fake(['from_long' => 'Stamm Beispiel']);
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
(new PreventionRememberMail($participant, app(PreventionSettings::class)->formmail))
|
||||||
|
->assertSeeInText($participant->member->firstname)
|
||||||
|
->assertSeeInText($participant->member->lastname)
|
||||||
|
->assertSeeInText('Stamm Beispiel');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItRendersSetttingMail(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
app(PreventionSettings::class)->fill([
|
||||||
|
'formmail' => EditorRequestFactory::new()->paragraphs(["lorem lala {formname} g", "{wanted}", "bbb"])->toData()
|
||||||
|
])->save();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$this->createParticipant($form);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
Mail::assertSent(PreventionRememberMail::class, fn ($mail) => $mail->bodyText->hasAll([
|
||||||
|
'lorem lala ' . $form->name,
|
||||||
|
'erweitertes'
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItAppendsTextOfForm(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
app(PreventionSettings::class)->fill([
|
||||||
|
'formmail' => EditorRequestFactory::new()->paragraphs(["::first::"])->toData()
|
||||||
|
])->save();
|
||||||
|
$form = $this->createForm();
|
||||||
|
$form->update(['prevention_text' => EditorRequestFactory::new()->paragraphs(['event'])->toData()]);
|
||||||
|
$this->createParticipant($form);
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
Mail::assertSent(PreventionRememberMail::class, fn ($mail) => $mail->bodyText->hasAll([
|
||||||
|
'event'
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntAppendTextTwice(): void
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
app(PreventionSettings::class)->fill(['frommail' => EditorRequestFactory::new()->paragraphs(["::first::"])->toData()])->save();
|
||||||
|
tap($this->createForm(), function ($f) {
|
||||||
|
$f->update(['prevention_text' => EditorRequestFactory::new()->paragraphs(['oberhausen'])->toData()]);
|
||||||
|
$this->createParticipant($f);
|
||||||
|
});
|
||||||
|
tap($this->createForm(), function ($f) {
|
||||||
|
$f->update(['prevention_text' => EditorRequestFactory::new()->paragraphs(['siegburg'])->toData()]);
|
||||||
|
$this->createParticipant($f);
|
||||||
|
});
|
||||||
|
|
||||||
|
PreventionRememberAction::run();
|
||||||
|
|
||||||
|
Mail::assertSent(PreventionRememberMail::class, fn ($mail) => $mail->bodyText->hasAll(['oberhausen']) && !$mail->bodyText->hasAll(['siegburg']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDisplaysBodyTextInMail(): void
|
||||||
|
{
|
||||||
|
$form = $this->createForm();
|
||||||
|
$participant = $this->createParticipant($form);
|
||||||
|
|
||||||
|
$mail = new PreventionRememberMail($participant, EditorRequestFactory::new()->paragraphs(['ggtt'])->toData());
|
||||||
|
$mail->assertSeeInText('ggtt');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createForm(): Form
|
||||||
|
{
|
||||||
|
return Form::factory()->fields([
|
||||||
|
$this->textField('vorname')->namiType(NamiType::FIRSTNAME)->specialType(SpecialType::FIRSTNAME),
|
||||||
|
$this->textField('nachname')->namiType(NamiType::FIRSTNAME)->specialType(SpecialType::LASTNAME),
|
||||||
|
$this->textField('email')->namiType(NamiType::FIRSTNAME)->specialType(SpecialType::EMAIL),
|
||||||
|
])->create(['needs_prevention' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createParticipant(Form $form): Participant
|
||||||
|
{
|
||||||
|
return Participant::factory()->for($form)->data([
|
||||||
|
'vorname' => 'Max',
|
||||||
|
'nachname' => 'Muster',
|
||||||
|
'email' => 'mail@a.de',
|
||||||
|
])->for(Member::factory()->defaults()->has(Membership::factory()->inLocal('€ LeiterIn', 'Wölfling')))->create();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Prevention;
|
||||||
|
|
||||||
|
use App\Prevention\PreventionSettings;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class SettingTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function testItOpensSettingsPage(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami();
|
||||||
|
|
||||||
|
$this->get('/setting/prevention')->assertComponent('setting/Prevention')->assertOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReceivesSettings(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami();
|
||||||
|
|
||||||
|
$text = EditorRequestFactory::new()->text(50, 'lorem ipsum')->toData();
|
||||||
|
app(PreventionSettings::class)->fill(['formmail' => $text])->save();
|
||||||
|
|
||||||
|
$this->get('/api/prevention')
|
||||||
|
->assertJsonPath('data.formmail.blocks.0.data.text', 'lorem ipsum');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItStoresSettings(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami();
|
||||||
|
|
||||||
|
$this->post('/api/prevention', ['formmail' => EditorRequestFactory::new()->text(50, 'new lorem')->create()])->assertOk();
|
||||||
|
$this->assertTrue(app(PreventionSettings::class)->formmail->hasAll(['new lorem']));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Tests\RequestFactories;
|
namespace Tests\RequestFactories;
|
||||||
|
|
||||||
|
use App\Lib\Editor\EditorData;
|
||||||
use Worksome\RequestFactories\RequestFactory;
|
use Worksome\RequestFactories\RequestFactory;
|
||||||
|
|
||||||
class EditorRequestFactory extends RequestFactory
|
class EditorRequestFactory extends RequestFactory
|
||||||
|
@ -20,6 +21,11 @@ class EditorRequestFactory extends RequestFactory
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function empty(): self
|
||||||
|
{
|
||||||
|
return $this->state(['blocks' => []]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $conditions
|
* @param array<string, mixed> $conditions
|
||||||
*/
|
*/
|
||||||
|
@ -49,4 +55,28 @@ class EditorRequestFactory extends RequestFactory
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, string> $paragraphs
|
||||||
|
*/
|
||||||
|
public function paragraphs(array $paragraphs): self
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
'time' => 1,
|
||||||
|
'version' => '1.0',
|
||||||
|
'blocks' => collect($paragraphs)->map(fn ($paragraph) => [
|
||||||
|
'id' => $this->faker->numberBetween([0, 10000]),
|
||||||
|
'type' => 'paragraph',
|
||||||
|
'data' => ['text' => $paragraph],
|
||||||
|
'tunes' => [
|
||||||
|
'condition' => ['mode' => 'all', 'ifs' => []]
|
||||||
|
]
|
||||||
|
])->toArray(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toData(): EditorData
|
||||||
|
{
|
||||||
|
return EditorData::from($this->create());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use Tests\RequestFactories\EditorRequestFactory;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class EditorDataTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testItReplacesBlockContentWithList(): void
|
||||||
|
{
|
||||||
|
$data = EditorRequestFactory::new()->paragraphs(['{search}'])->toData();
|
||||||
|
|
||||||
|
$data->replaceWithList('search', ['A', 'B']);
|
||||||
|
|
||||||
|
$this->assertEquals('A', data_get($data->blocks, '0.data.items.0.content'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Illuminate\Testing;
|
||||||
|
|
||||||
|
namespace Spatie\LaravelSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static refresh()
|
||||||
|
*/
|
||||||
|
abstract class Settings
|
||||||
|
{
|
||||||
|
}
|
Loading…
Reference in New Issue