From 5cdc4df5cdb1bcf25d53344fd1036c33636035e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 17:18:31 +0200 Subject: [PATCH 1/9] ignore PhpStorm project files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 39783ad..d2d88a7 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,6 @@ config/local.neon npm-debug.log* yarn-debug.log* yarn-error.log* +.idea/ -bin/objednavky \ No newline at end of file +bin/objednavky From 879adb8196665b5c62335278963fa2d4cabd189e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 17:42:44 +0200 Subject: [PATCH 2/9] temp fix for db connection through console --- config/common.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/common.neon b/config/common.neon index 795de4d..5c6e234 100644 --- a/config/common.neon +++ b/config/common.neon @@ -30,7 +30,7 @@ di: nettrine.dbal: connection: driver: pdo_mysql - host: 127.0.0.1 + host: mysql # could not connect through command line, may be some config include priority problem dbname: invoice-test-app charset: utf8 user: From f8022e9fa546bce8417cc190e4217e361abfd195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 18:39:59 +0200 Subject: [PATCH 3/9] Proper PSR-4 autoloading --- app/{presenters => Presenters}/ClientDetailPresenter.php | 0 app/{presenters => Presenters}/Error4xxPresenter.php | 0 app/{presenters => Presenters}/ErrorPresenter.php | 0 app/{presenters => Presenters}/HomepagePresenter.php | 0 app/{presenters => Presenters}/templates/@commonBlocks.latte | 0 app/{presenters => Presenters}/templates/@layout.latte | 0 .../templates/ClientDetail/default.latte | 0 app/{presenters => Presenters}/templates/Error/500.phtml | 0 app/{presenters => Presenters}/templates/Error/503.phtml | 0 app/{presenters => Presenters}/templates/Error4xx/403.latte | 0 app/{presenters => Presenters}/templates/Error4xx/404.latte | 0 app/{presenters => Presenters}/templates/Error4xx/405.latte | 0 app/{presenters => Presenters}/templates/Error4xx/410.latte | 0 app/{presenters => Presenters}/templates/Error4xx/4xx.latte | 0 app/{presenters => Presenters}/templates/Homepage/default.latte | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename app/{presenters => Presenters}/ClientDetailPresenter.php (100%) rename app/{presenters => Presenters}/Error4xxPresenter.php (100%) rename app/{presenters => Presenters}/ErrorPresenter.php (100%) rename app/{presenters => Presenters}/HomepagePresenter.php (100%) rename app/{presenters => Presenters}/templates/@commonBlocks.latte (100%) rename app/{presenters => Presenters}/templates/@layout.latte (100%) rename app/{presenters => Presenters}/templates/ClientDetail/default.latte (100%) rename app/{presenters => Presenters}/templates/Error/500.phtml (100%) rename app/{presenters => Presenters}/templates/Error/503.phtml (100%) rename app/{presenters => Presenters}/templates/Error4xx/403.latte (100%) rename app/{presenters => Presenters}/templates/Error4xx/404.latte (100%) rename app/{presenters => Presenters}/templates/Error4xx/405.latte (100%) rename app/{presenters => Presenters}/templates/Error4xx/410.latte (100%) rename app/{presenters => Presenters}/templates/Error4xx/4xx.latte (100%) rename app/{presenters => Presenters}/templates/Homepage/default.latte (100%) diff --git a/app/presenters/ClientDetailPresenter.php b/app/Presenters/ClientDetailPresenter.php similarity index 100% rename from app/presenters/ClientDetailPresenter.php rename to app/Presenters/ClientDetailPresenter.php diff --git a/app/presenters/Error4xxPresenter.php b/app/Presenters/Error4xxPresenter.php similarity index 100% rename from app/presenters/Error4xxPresenter.php rename to app/Presenters/Error4xxPresenter.php diff --git a/app/presenters/ErrorPresenter.php b/app/Presenters/ErrorPresenter.php similarity index 100% rename from app/presenters/ErrorPresenter.php rename to app/Presenters/ErrorPresenter.php diff --git a/app/presenters/HomepagePresenter.php b/app/Presenters/HomepagePresenter.php similarity index 100% rename from app/presenters/HomepagePresenter.php rename to app/Presenters/HomepagePresenter.php diff --git a/app/presenters/templates/@commonBlocks.latte b/app/Presenters/templates/@commonBlocks.latte similarity index 100% rename from app/presenters/templates/@commonBlocks.latte rename to app/Presenters/templates/@commonBlocks.latte diff --git a/app/presenters/templates/@layout.latte b/app/Presenters/templates/@layout.latte similarity index 100% rename from app/presenters/templates/@layout.latte rename to app/Presenters/templates/@layout.latte diff --git a/app/presenters/templates/ClientDetail/default.latte b/app/Presenters/templates/ClientDetail/default.latte similarity index 100% rename from app/presenters/templates/ClientDetail/default.latte rename to app/Presenters/templates/ClientDetail/default.latte diff --git a/app/presenters/templates/Error/500.phtml b/app/Presenters/templates/Error/500.phtml similarity index 100% rename from app/presenters/templates/Error/500.phtml rename to app/Presenters/templates/Error/500.phtml diff --git a/app/presenters/templates/Error/503.phtml b/app/Presenters/templates/Error/503.phtml similarity index 100% rename from app/presenters/templates/Error/503.phtml rename to app/Presenters/templates/Error/503.phtml diff --git a/app/presenters/templates/Error4xx/403.latte b/app/Presenters/templates/Error4xx/403.latte similarity index 100% rename from app/presenters/templates/Error4xx/403.latte rename to app/Presenters/templates/Error4xx/403.latte diff --git a/app/presenters/templates/Error4xx/404.latte b/app/Presenters/templates/Error4xx/404.latte similarity index 100% rename from app/presenters/templates/Error4xx/404.latte rename to app/Presenters/templates/Error4xx/404.latte diff --git a/app/presenters/templates/Error4xx/405.latte b/app/Presenters/templates/Error4xx/405.latte similarity index 100% rename from app/presenters/templates/Error4xx/405.latte rename to app/Presenters/templates/Error4xx/405.latte diff --git a/app/presenters/templates/Error4xx/410.latte b/app/Presenters/templates/Error4xx/410.latte similarity index 100% rename from app/presenters/templates/Error4xx/410.latte rename to app/Presenters/templates/Error4xx/410.latte diff --git a/app/presenters/templates/Error4xx/4xx.latte b/app/Presenters/templates/Error4xx/4xx.latte similarity index 100% rename from app/presenters/templates/Error4xx/4xx.latte rename to app/Presenters/templates/Error4xx/4xx.latte diff --git a/app/presenters/templates/Homepage/default.latte b/app/Presenters/templates/Homepage/default.latte similarity index 100% rename from app/presenters/templates/Homepage/default.latte rename to app/Presenters/templates/Homepage/default.latte From 8b4c035c8545463cd0adf32d07dcf90c6005112b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 19:41:38 +0200 Subject: [PATCH 4/9] refactor entities, presenter, templates a bit - use attributes instead of annotations, add new dueDate property to invoice and so.. --- app/Mails/templates/invoice.latte | 4 +- app/Model/Entities/Client.php | 71 +++----- app/Model/Entities/Invoice.php | 92 ++++++----- app/Model/InvoiceService.php | 17 +- app/Presenters/ClientDetailPresenter.php | 103 ------------ app/Presenters/ClientPresenter.php | 153 ++++++++++++++++++ .../default.latte => Client/detail.latte} | 19 ++- .../templates/Homepage/default.latte | 10 +- config/common.neon | 10 +- migrations/Version20221019160643.php | 40 +++++ 10 files changed, 308 insertions(+), 211 deletions(-) delete mode 100644 app/Presenters/ClientDetailPresenter.php create mode 100644 app/Presenters/ClientPresenter.php rename app/Presenters/templates/{ClientDetail/default.latte => Client/detail.latte} (63%) create mode 100644 migrations/Version20221019160643.php diff --git a/app/Mails/templates/invoice.latte b/app/Mails/templates/invoice.latte index bbc19d8..ba69879 100644 --- a/app/Mails/templates/invoice.latte +++ b/app/Mails/templates/invoice.latte @@ -5,5 +5,5 @@ {block title}Nová faktura{/block} {block content} -

Částka: {$invoice->amount|number:2, ',', ' '} Kč

-

Datum vystavení: {$invoice->issueDate|date:'j. n. Y'}

+

Částka: {$invoice->getAmount()|number:2, ',', ' '} Kč

+

Datum vystavení: {$invoice->getIssueDate()|date:'j. n. Y'}

diff --git a/app/Model/Entities/Client.php b/app/Model/Entities/Client.php index 971ca68..cd155ac 100644 --- a/app/Model/Entities/Client.php +++ b/app/Model/Entities/Client.php @@ -4,56 +4,44 @@ namespace Netvor\Invoice\Model\Entities; +use DateTimeImmutable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Nette; - - -/** - * @ORM\Entity - * @property-read ?int $id - * @property-read string $ic - * @property-read string $email - * @property-read string $firstName - * @property-read string $lastName - * @property-read string $street - * @property-read string $city - * @property-read string $postalCode - * @property-read Nette\Utils\DateTime $createdAt - */ + +#[ORM\Entity] class Client { - use Nette\SmartObject; - - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: Types::INTEGER)] + #[ORM\Id] + #[ORM\GeneratedValue] private ?int $id = null; - /** @ORM\Column */ + #[ORM\Column] private string $ic; - /** @ORM\Column(unique=true) */ + #[ORM\Column(unique: true)] private string $email; - /** @ORM\Column */ + #[ORM\Column] private string $firstName; - /** @ORM\Column */ + #[ORM\Column] private string $lastName; - /** @ORM\Column */ + #[ORM\Column] private string $street; - /** @ORM\Column */ + #[ORM\Column] private string $city; - /** @ORM\Column */ + #[ORM\Column] private string $postalCode; - /** @ORM\Column(type="datetime", options={"default": "CURRENT_TIMESTAMP"}) */ - private \DateTime $createdAt; + #[ORM\Column( + type: Types::DATETIME_IMMUTABLE, + options: ['default' => 'CURRENT_TIMESTAMP'], + )] + private DateTimeImmutable $createdAt; public function __construct( @@ -73,7 +61,7 @@ public function __construct( $this->setCity($city); $this->setPostalCode($postalCode); - $this->createdAt = new Nette\Utils\DateTime; + $this->createdAt = new DateTimeImmutable; } @@ -95,9 +83,6 @@ public function getIc(): string } - /** - * @return $this - */ public function setIc(string $ic): self { $this->ic = $ic; @@ -124,9 +109,6 @@ public function getFirstName(): string } - /** - * @return $this - */ public function setFirstName(string $firstName): self { $this->firstName = $firstName; @@ -140,9 +122,6 @@ public function getLastName(): string } - /** - * @return $this - */ public function setLastName(string $lastName): self { $this->lastName = $lastName; @@ -169,9 +148,6 @@ public function getCity(): string } - /** - * @return $this - */ public function setCity(string $city): self { $this->city = $city; @@ -185,9 +161,6 @@ public function getPostalCode(): string } - /** - * @return $this - */ public function setPostalCode(string $postalCode): self { $this->postalCode = $postalCode; @@ -195,8 +168,8 @@ public function setPostalCode(string $postalCode): self } - public function getCreatedAt(): Nette\Utils\DateTime + public function getCreatedAt(): DateTimeImmutable { - return Nette\Utils\DateTime::from($this->createdAt); + return $this->createdAt; } } diff --git a/app/Model/Entities/Invoice.php b/app/Model/Entities/Invoice.php index 7819298..f53fb1e 100644 --- a/app/Model/Entities/Invoice.php +++ b/app/Model/Entities/Invoice.php @@ -4,46 +4,53 @@ namespace Netvor\Invoice\Model\Entities; +use DateTimeImmutable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Nette; +use InvalidArgumentException; +use Nette\Utils\Validators; -/** - * @ORM\Entity - * @property-read ?int $id - * @property-read Client $client - * @property-read string $amount - * @property-read Nette\Utils\DateTime $issueDate - */ +#[ORM\Entity] class Invoice { - use Nette\SmartObject; - - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: Types::INTEGER)] + #[ORM\Id] + #[ORM\GeneratedValue] private ?int $id = null; - /** - * @ORM\ManyToOne(targetEntity="Client") - * @ORM\JoinColumn(nullable=false, onDelete="CASCADE") - */ + #[ORM\ManyToOne(targetEntity: Client::class)] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private Client $client; - /** @ORM\Column(type="decimal", precision=12, scale=2) */ + #[ORM\Column(type: Types::DECIMAL, precision: 12, scale: 2)] private string $amount; - /** @ORM\Column(type="datetime", options={"default": "CURRENT_TIMESTAMP"}) */ - private \DateTime $issueDate; - - - public function __construct(Client $client, string $amount, \DateTime $issueDate) + #[ORM\Column( + type: Types::DATETIME_IMMUTABLE, + options: ['default' => 'CURRENT_TIMESTAMP'], + )] + private DateTimeImmutable $issueDate; + + // must be nullable, because we can already have some data in db if already in production + // and that would end-up with error, since current rows have no default value + // some different strategy can be used, just to be sure for this case, where we already have data + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] + private ?DateTimeImmutable $dueDate; + + + public function __construct( + Client $client, + string $amount, + DateTimeImmutable $issueDate, + ?DateTimeImmutable $dueDate = null, + ) { - $this->client = $client; $this->setAmount($amount); - $this->setIssueDate($issueDate); + + $this->client = $client; + $this->issueDate = $issueDate; + $this->dueDate = $dueDate; } @@ -71,13 +78,10 @@ public function getAmount(): string } - /** - * @return $this - */ public function setAmount(string $amount): self { - if (!Nette\Utils\Validators::isNumeric($amount)) { - throw new \InvalidArgumentException; + if (Validators::isNumeric($amount) === false) { + throw new InvalidArgumentException; } $this->amount = $amount; @@ -85,18 +89,28 @@ public function setAmount(string $amount): self } - public function getIssueDate(): Nette\Utils\DateTime + public function getDueDate(): ?DateTimeImmutable + { + return $this->dueDate; + } + + + public function setDueDate(?DateTimeImmutable $dueDate): self + { + $this->dueDate = $dueDate; + return $this; + } + + + public function getIssueDate(): DateTimeImmutable { - return Nette\Utils\DateTime::from($this->issueDate); + return $this->issueDate; } - /** - * @return $this - */ - public function setIssueDate(\DateTime $issueDate): self + public function setIssueDate(DateTimeImmutable $issueDate): self { - $this->issueDate = Nette\Utils\DateTime::from($issueDate); + $this->issueDate = $issueDate; return $this; } } diff --git a/app/Model/InvoiceService.php b/app/Model/InvoiceService.php index 5a93d49..fe11574 100644 --- a/app/Model/InvoiceService.php +++ b/app/Model/InvoiceService.php @@ -4,8 +4,10 @@ namespace Netvor\Invoice\Model; +use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\Persistence\ObjectRepository; use Nette; use Netvor\Invoice\Mails\MailService; @@ -16,8 +18,9 @@ class InvoiceService private EntityManagerInterface $entityManager; + // interface better /** @var EntityRepository */ - private EntityRepository $repository; + private ObjectRepository $repository; private MailService $mailService; @@ -48,9 +51,15 @@ public function getAllByClient(Entities\Client $client): array } - public function create(Entities\Client $client, string $amount, \DateTime $issueDate): Entities\Invoice - { - $invoice = new Entities\Invoice($client, $amount, $issueDate); + public function create( + Entities\Client $client, + string $amount, + DateTimeImmutable $issueDate, + DateTimeImmutable $dueDate, + ): Entities\Invoice { + // this method should be split into its own class, since this class has multiple purposes cuz of this method + // leave it out like this for now + $invoice = new Entities\Invoice($client, $amount, $issueDate, $dueDate); $this->entityManager->persist($invoice); $this->entityManager->flush(); diff --git a/app/Presenters/ClientDetailPresenter.php b/app/Presenters/ClientDetailPresenter.php deleted file mode 100644 index 7c2307a..0000000 --- a/app/Presenters/ClientDetailPresenter.php +++ /dev/null @@ -1,103 +0,0 @@ -client = $this->checkClient($id); - } - - - public function renderDefault(): void - { - $this->template->client = $this->client; - $this->template->invoices = $this->invoiceModel->getAllByClient($this->client); - - $this['invoiceForm']->setDefaults([ - 'issueDate' => date('Y-m-d'), - ]); - } - - - protected function createComponentInvoiceForm(): UI\Form - { - $form = new UI\Form; - $form->addProtection('Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'); - - $form->addText('amount') - ->setRequired('Zadejte prosím částku.') - ->addRule(UI\Form::NUMERIC, 'Zadejte prosím číslo.'); - - $form->addText('issueDate') - ->setHtmlType('date') - ->setRequired('Zvolte prosím datum.'); - - $form->addSubmit('submit'); - - $form->onSuccess[] = [$this, 'invoiceFormSucceeded']; - $form->onError[] = function (): void { - if ($this->isAjax()) { - $this->redrawControl('invoiceForm'); - } - }; - - return $form; - } - - - public function invoiceFormSucceeded(UI\Form $form, \stdClass $data): void - { - try { - $issueDate = new Nette\Utils\DateTime($data->issueDate); - } catch (\Exception $e) { - /** @var Nette\Forms\Controls\TextInput $issueDateInput */ - $issueDateInput = $form['issueDate']; - $issueDateInput->addError('Zadejte prosím platné datum.'); - return; - } - - $this->invoiceModel->create($this->client, $data->amount, $issueDate); - - if (!$this->isAjax()) { - $this->redirect('this'); - } - - $form->reset(); - $this->payload->postGet = true; - $this->payload->url = $this->link('this'); - $this->redrawControl('invoiceForm'); - $this->redrawControl('invoicesTable'); - } - - - private function checkClient(int $id): Client - { - $client = $this->model->get($id); - if ($client === null) { - $this->flashMessage('Klient nebyl nalezen.', 'danger'); - $this->redirect('Homepage:'); - } - - return $client; - } -} diff --git a/app/Presenters/ClientPresenter.php b/app/Presenters/ClientPresenter.php new file mode 100644 index 0000000..55c1cc5 --- /dev/null +++ b/app/Presenters/ClientPresenter.php @@ -0,0 +1,153 @@ +model->get($id); + + if ($client === null) { + $this->flashMessage('Klient nebyl nalezen.', 'danger'); + $this->redirect('Homepage:'); + return; // to be sure + } + + $this->client = $client; + } + + + public function renderDetail(): void + { + $this->template->client = $this->client; + $this->template->invoices = $this->invoiceModel->getAllByClient($this->client); + + // now we have correct data type + /** @var UI\Form $invoiceForm */ + $invoiceForm = $this['invoiceForm']; + $invoiceForm->setDefaults([ + 'issueDate' => date('Y-m-d'), + 'dueDate' => date('Y-m-d'), + ]); + } + + + protected function createComponentInvoiceForm(): UI\Form + { + // TODO: translate + $form = new UI\Form; + $form->addProtection('Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'); + + $form->addText('amount') + ->setRequired('Zadejte prosím částku.') + ->addRule(UI\Form::NUMERIC, 'Zadejte prosím číslo.'); + + $form->addText('issueDate') + ->setHtmlType('date') + ->setRequired('Zvolte prosím datum vytavení'); + + $form->addText('dueDate') + ->setHtmlType('date') + ->setRequired('Zvolte prosím datum splatnosti'); + + $form->addSubmit('submit'); + + $form->onSuccess[] = [$this, 'invoiceFormSucceeded']; + $form->onValidate[] = [$this, 'invoiceFormValidate']; + $form->onError[] = function (): void { + if ($this->isAjax()) { + $this->redrawControl('invoiceForm'); + } + }; + + return $form; + } + + + /** + * @throws InvalidLinkException + * @throws AbortException + */ + public function invoiceFormValidate(UI\Form $form, stdClass $data): void + { + $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + + if ($issueDate === false) { + /** @var Nette\Forms\Controls\TextInput $issueDateInput */ + $issueDateInput = $form['issueDate']; + $issueDateInput->addError('Zadejte prosím platné datum.'); + } + + $dueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + + if ($dueDate === false) { + /** @var Nette\Forms\Controls\TextInput $dueDate */ + $dueDateInput = $form['dueDate']; + $dueDateInput->addError('Zadejte prosím platné datum.'); + } + + // clear, not exactly necessary + unset($issueDate, $dueDate); + + if ($this->isAjax() === false) { + $this->redirect('this'); + return; + } + + $this->redrawControl('invoiceForm'); + $this->redrawControl('invoicesTable'); + } + + + /** + * @throws InvalidLinkException + * @throws AbortException + */ + public function invoiceFormSucceeded(UI\Form $form, stdClass $data): void + { + $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + $dueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->dueDate); + + $this->invoiceModel->create($this->client, $data->amount, $issueDate, $dueDate); + + if ($this->isAjax() === false) { + $this->redirect('this'); + } + + $form->reset(); + $this->payload->postGet = true; + $this->payload->url = $this->link('this'); + $this->redrawControl('invoiceForm'); + $this->redrawControl('invoicesTable'); + } +} diff --git a/app/Presenters/templates/ClientDetail/default.latte b/app/Presenters/templates/Client/detail.latte similarity index 63% rename from app/Presenters/templates/ClientDetail/default.latte rename to app/Presenters/templates/Client/detail.latte index 835c0e7..f26f04c 100644 --- a/app/Presenters/templates/ClientDetail/default.latte +++ b/app/Presenters/templates/Client/detail.latte @@ -5,7 +5,7 @@ {block content} -

Faktury klienta {$client->firstName} {$client->lastName} ({$client->ic})

+

Faktury klienta {$client->getFirstName()} {$client->getLastName()} ({$client->getIc()})


Nová faktura

@@ -23,6 +23,11 @@ {include inputErrors input => $form[issueDate]} +
+ + + {include inputErrors input => $form[dueDate]} +
@@ -35,12 +40,20 @@ Částka Datum vystavení + Datum splatnosti - {$invoice->amount|number:2, ',', ' '} Kč - {$invoice->issueDate|date:'j. n. Y'} + {$invoice->getAmount()|number:2, ',', ' '} Kč + {$invoice->getIssueDate()|date:'j. n. Y'} + + {if $invoice->getDueDate() !== null} + {$invoice->getDueDate()|date:'j. n. Y'} + {else} + - + {/if} + diff --git a/app/Presenters/templates/Homepage/default.latte b/app/Presenters/templates/Homepage/default.latte index 0d4cbd6..9d21309 100644 --- a/app/Presenters/templates/Homepage/default.latte +++ b/app/Presenters/templates/Homepage/default.latte @@ -69,12 +69,12 @@ - {$client->ic} - {$client->email} - {$client->firstName} {$client->lastName} - {[$client->street, $client->city, $client->postalCode]|join:', '} + {$client->getIc()} + {$client->getEmail()} + {$client->getFirstName()} {$client->getLastName()} + {[$client->getStreet(), $client->getCity(), $client->getPostalCode()]|join:', '} - Detail + Detail diff --git a/config/common.neon b/config/common.neon index 5c6e234..8a8fb79 100644 --- a/config/common.neon +++ b/config/common.neon @@ -9,7 +9,7 @@ extensions: nettrine.cache: Nettrine\Cache\DI\CacheExtension nettrine.dbal: Nettrine\DBAL\DI\DbalExtension nettrine.orm: Nettrine\ORM\DI\OrmExtension - nettrine.orm.annotations: Nettrine\ORM\DI\OrmAnnotationsExtension + nettrine.orm.attributes: Nettrine\ORM\DI\OrmAttributesExtension nettrine.orm.cache: Nettrine\ORM\DI\OrmCacheExtension webpack: Contributte\Webpack\DI\WebpackExtension(%debugMode%, %consoleMode%) @@ -41,11 +41,9 @@ nettrine.dbal: debug: panel: %debugMode% - -nettrine.orm.annotations: - mapping: - Netvor\Invoice: %appDir% - +nettrine.orm.attributes: + mapping: + Netvor\Invoice: %appDir% session: autoStart: always diff --git a/migrations/Version20221019160643.php b/migrations/Version20221019160643.php new file mode 100644 index 0000000..21bb267 --- /dev/null +++ b/migrations/Version20221019160643.php @@ -0,0 +1,40 @@ +hasTable('invoice') === true) { + $table = $schema->getTable('invoice'); + if ($table->hasColumn('due_date') === false) { + $table->addColumn('due_date', Types::DATETIME_IMMUTABLE)->setNotnull(false); + } + } + } + + + public function down(Schema $schema): void + { + if ($schema->hasTable('invoice') === true) { + $table = $schema->getTable('invoice'); + if ($table->hasColumn('due_date') === true) { + // TODO: dump to some SQL file to prevent data loss on rollback? + $table->dropColumn('due_date'); + } + } + } +} From b344ecfcf274bbcb5aebbe450b95ec90d55e685e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 23:48:28 +0200 Subject: [PATCH 5/9] add payment form --- app/Form/InvoiceForm/InvoiceForm.latte | 45 +++++ app/Form/InvoiceForm/InvoiceForm.php | 186 +++++++++++++++++++ app/Form/InvoiceForm/InvoiceFormFactory.php | 13 ++ app/Mails/templates/invoice.latte | 2 +- app/Model/Entities/Invoice.php | 83 +++++++-- app/Model/Entities/Payment.php | 94 ++++++++++ app/Model/InvoiceService.php | 11 +- app/Presenters/ClientPresenter.php | 115 +++--------- app/Presenters/templates/Client/detail.latte | 33 +--- composer.json | 3 +- composer.lock | 88 ++++++++- config/common.neon | 3 + docker-compose.yml | 2 +- migrations/Version20221019180709.php | 73 ++++++++ 14 files changed, 620 insertions(+), 131 deletions(-) create mode 100644 app/Form/InvoiceForm/InvoiceForm.latte create mode 100644 app/Form/InvoiceForm/InvoiceForm.php create mode 100644 app/Form/InvoiceForm/InvoiceFormFactory.php create mode 100644 app/Model/Entities/Payment.php create mode 100644 migrations/Version20221019180709.php diff --git a/app/Form/InvoiceForm/InvoiceForm.latte b/app/Form/InvoiceForm/InvoiceForm.latte new file mode 100644 index 0000000..81205bb --- /dev/null +++ b/app/Form/InvoiceForm/InvoiceForm.latte @@ -0,0 +1,45 @@ +{import ../../Presenters/templates/@commonBlocks.latte} + +{varType ?Netvor\Invoice\Model\Entities\Invoice $invoice} + +{if $invoice === null} {* We have no invoice yet, then create one. *} +

Nová faktura

+
+
+ {include formErrors form => $form} +
+
+ + + {include inputErrors input => $form[amount]} +
+
+ + + {include inputErrors input => $form[issueDate]} +
+
+ + + {include inputErrors input => $form[dueDate]} +
+
+ +
+
+{else} {* We have invoice, add payment if wanted. *} +

Přidat platbu k faktuře {$invoice->getId()}

+
+
+ {include formErrors form => $form} +
+
+ + + {include inputErrors input => $form[amount]} +
+
+ +
+
+{/if} diff --git a/app/Form/InvoiceForm/InvoiceForm.php b/app/Form/InvoiceForm/InvoiceForm.php new file mode 100644 index 0000000..cdad192 --- /dev/null +++ b/app/Form/InvoiceForm/InvoiceForm.php @@ -0,0 +1,186 @@ +template->setFile(__DIR__ . '/InvoiceForm.latte'); + $this->template->invoice = $this->invoice; + $this->template->render(); + } + + + public function createComponentPaymentForm(): Form + { + $form = new Form; + $form->addProtection('Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'); + + $form->addText('amount') + ->setRequired('Zadejte prosím částku.'); + + $form->addHidden('invoiceId', $this->invoice?->getId() ?? null) + ->setRequired(); + $form->addSubmit('submit'); + + $form->onValidate[] = [$this, 'paymentFormValidate']; + $form->onSuccess[] = [$this, 'paymentFormSuccess']; + $form->onError[] = function (): void { + if ($this->getPresenter()->isAjax() === true) { + $this->redrawControl('paymentForm'); + return; + } + + $this->redirect('this'); + }; + + return $form; + } + + + public function paymentFormValidate(Form $form, stdClass $data): void + { + if (Validators::isNumeric($data->amount) === false) { + /** @var TextInput $amountInput */ + $amountInput = $form['amount']; + $amountInput->addError('Částka musí být validní číslo.'); + } + } + + + public function paymentFormSuccess(Form $form, stdClass $data): void + { + $this->invoice = $this->invoiceService->get((int) $data->invoiceId); + + if ($this->invoice === null) { + $form->addError('Faktura ke které se snažíte přidat platbu neexistuje.'); + return; + } + + $amount = Money::CZK((int) ((float) $data->amount * 100)); // TODO: currency + $unpaidAmount = $this->invoice->getUnpaidAmount(); + + if ((int) $amount->getAmount() > $unpaidAmount) { + /** @var TextInput $amountInput */ + $amountInput = $form['amount']; + $amountInput->addError(sprintf('Částka nemůže převyšovat %dKč.', $unpaidAmount / 100)); + return; + } + + $this->invoiceService->addPayment(new Payment($this->invoice, $amount)); + $this->invoice = null; + } + + + protected function createComponentInvoiceForm(): Form + { + // TODO: translate + $form = new Form; + $form->addProtection('Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'); + + $form->addText('amount') + ->setRequired('Zadejte prosím částku.'); + + $form->addText('issueDate') + ->setHtmlType('date') + ->setRequired('Zvolte prosím datum vytavení') + ->setDefaultValue(date('Y-m-d')); + + $form->addText('dueDate') + ->setHtmlType('date') + ->setRequired('Zvolte prosím datum splatnosti') + ->setDefaultValue(date('Y-m-d')); + + $form->addSubmit('submit'); + + $form->onSuccess[] = [$this, 'invoiceFormSuccess']; + $form->onValidate[] = [$this, 'invoiceFormValidate']; + $form->onError[] = function (): void { + if ($this->getPresenter()->isAjax() === true) { + $this->redrawControl('invoiceForm'); + return; + } + + $this->redirect('this'); + }; + + return $form; + } + + + /** + * @throws AbortException + */ + protected function invoiceFormValidate(Form $form, stdClass $data): void + { + // TODO: translate + if (Validators::isNumeric($data->amount) === false) { + /** @var TextInput $amountInput */ + $amountInput = $form['amount']; + $amountInput->addError('Částka musí být validní číslo.'); + } + } + + + /** + * @throws AbortException + */ + protected function invoiceFormSuccess(Form $form, stdClass $data): void + { + $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + + if ($issueDate === false) { + /** @var TextInput $issueDateInput */ + $issueDateInput = $form['issueDate']; + $issueDateInput->addError('Zadejte prosím platné datum.'); + return; + } + + $dueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + + if ($dueDate === false) { + /** @var TextInput $dueDateInput */ + $dueDateInput = $form['dueDate']; + $dueDateInput->addError('Zadejte prosím platné datum.'); + return; + } + + $amount = Money::CZK((int) ((float) $data->amount * 100)); // TODO: currency + $this->invoiceService->create($this->client, $amount, $issueDate, $dueDate); + + if ($this->getPresenter()->isAjax() === false) { + $this->redirect('this'); + } + + $form->reset(); + $this->redrawControl('invoiceForm'); + } +} diff --git a/app/Form/InvoiceForm/InvoiceFormFactory.php b/app/Form/InvoiceForm/InvoiceFormFactory.php new file mode 100644 index 0000000..ff604b3 --- /dev/null +++ b/app/Form/InvoiceForm/InvoiceFormFactory.php @@ -0,0 +1,13 @@ +Částka: {$invoice->getAmount()|number:2, ',', ' '} Kč

+

Částka: {$invoice->getAmount()->getAmount() / 100|number:2, ',', ' '} Kč

Datum vystavení: {$invoice->getIssueDate()|date:'j. n. Y'}

diff --git a/app/Model/Entities/Invoice.php b/app/Model/Entities/Invoice.php index f53fb1e..395d799 100644 --- a/app/Model/Entities/Invoice.php +++ b/app/Model/Entities/Invoice.php @@ -5,10 +5,11 @@ namespace Netvor\Invoice\Model\Entities; use DateTimeImmutable; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use InvalidArgumentException; -use Nette\Utils\Validators; +use Money\Money; #[ORM\Entity] @@ -23,8 +24,8 @@ class Invoice #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private Client $client; - #[ORM\Column(type: Types::DECIMAL, precision: 12, scale: 2)] - private string $amount; + #[ORM\Column(type: Types::STRING)] + private int $amount; #[ORM\Column( type: Types::DATETIME_IMMUTABLE, @@ -38,16 +39,20 @@ class Invoice #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] private ?DateTimeImmutable $dueDate; + /** @var Collection */ + #[ORM\OneToMany(mappedBy: 'invoice', targetEntity: Payment::class, fetch: 'EAGER')] + private Collection $payments; + public function __construct( Client $client, - string $amount, + Money $amount, DateTimeImmutable $issueDate, ?DateTimeImmutable $dueDate = null, - ) - { - $this->setAmount($amount); + ) { + $this->payments = new ArrayCollection; + $this->setAmount($amount); $this->client = $client; $this->issueDate = $issueDate; $this->dueDate = $dueDate; @@ -72,19 +77,16 @@ public function getClient(): Client } - public function getAmount(): string + public function getAmount(): Money { - return $this->amount; + // TODO: currency + return Money::CZK($this->amount); } - public function setAmount(string $amount): self + public function setAmount(Money $amount): self { - if (Validators::isNumeric($amount) === false) { - throw new InvalidArgumentException; - } - - $this->amount = $amount; + $this->amount = (int) $amount->getAmount(); return $this; } @@ -113,4 +115,53 @@ public function setIssueDate(DateTimeImmutable $issueDate): self $this->issueDate = $issueDate; return $this; } + + + public function getPaidAmount(): int + { + $paidAmount = 0; + + foreach ($this->payments as $payment) { + $paidAmount += (int) $payment->getAmount()->getAmount(); + } + + return $paidAmount; + } + + + public function getUnpaidAmount(): int + { + $unpaidAmount = $this->amount; + + foreach ($this->payments as $payment) { + $unpaidAmount -= (int) $payment->getAmount()->getAmount(); + } + + return $unpaidAmount; + } + + + /** @return Payment[] */ + public function getPayments(): array + { + return $this->payments->toArray(); + } + + + /** @param Payment[] $payments */ + public function setPayments(array $payments): self + { + $this->payments = new ArrayCollection($payments); + + return $this; + } + + + public function addPayment(Payment $payment): self + { + $payment->setInvoice($this); + $this->payments[] = $payment; + + return $this; + } } diff --git a/app/Model/Entities/Payment.php b/app/Model/Entities/Payment.php new file mode 100644 index 0000000..1d6d26d --- /dev/null +++ b/app/Model/Entities/Payment.php @@ -0,0 +1,94 @@ + 'CURRENT_TIMESTAMP'], + )] + private DateTimeImmutable $createdAt; + + + public function __construct(Invoice $invoice, Money $amount) + { + $this->invoice = $invoice; + $this->createdAt = new DateTimeImmutable; + + $this->setAmount($amount); + } + + + public function __clone() + { + $this->id = null; + } + + + public function getId(): ?int + { + return $this->id; + } + + + public function getInvoice(): Invoice + { + return $this->invoice; + } + + + public function setInvoice(Invoice $invoice): self + { + $this->invoice = $invoice; + return $this; + } + + + public function getAmount(): Money + { + // TODO: currency + return Money::CZK($this->amount); + } + + + public function setAmount(Money $amount): self + { + $this->amount = (int) $amount->getAmount(); + return $this; + } + + + public function getCreatedAt(): DateTimeImmutable + { + return $this->createdAt; + } + + + public function setCreatedAt(DateTimeImmutable $createdAt): self + { + $this->createdAt = $createdAt; + return $this; + } +} diff --git a/app/Model/InvoiceService.php b/app/Model/InvoiceService.php index fe11574..b1ecd45 100644 --- a/app/Model/InvoiceService.php +++ b/app/Model/InvoiceService.php @@ -8,8 +8,10 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectRepository; +use Money\Money; use Nette; use Netvor\Invoice\Mails\MailService; +use Netvor\Invoice\Model\Entities\Payment; class InvoiceService @@ -51,9 +53,16 @@ public function getAllByClient(Entities\Client $client): array } + public function addPayment(Payment $payment): void + { + $this->entityManager->persist($payment); + $this->entityManager->flush(); + } + + public function create( Entities\Client $client, - string $amount, + Money $amount, DateTimeImmutable $issueDate, DateTimeImmutable $dueDate, ): Entities\Invoice { diff --git a/app/Presenters/ClientPresenter.php b/app/Presenters/ClientPresenter.php index 55c1cc5..001e296 100644 --- a/app/Presenters/ClientPresenter.php +++ b/app/Presenters/ClientPresenter.php @@ -4,15 +4,14 @@ namespace Netvor\Invoice\Presenters; -use DateTimeImmutable; -use Nette; use Nette\Application\AbortException; use Nette\Application\UI; -use Nette\Application\UI\InvalidLinkException; +use Netvor\Invoice\Form\InvoiceForm\InvoiceForm; +use Netvor\Invoice\Form\InvoiceForm\InvoiceFormFactory; use Netvor\Invoice\Model\ClientService; use Netvor\Invoice\Model\Entities\Client; +use Netvor\Invoice\Model\Entities\Invoice; use Netvor\Invoice\Model\InvoiceService; -use stdClass; /** * @property-read UI\Template $template @@ -20,11 +19,13 @@ final class ClientPresenter extends UI\Presenter { private Client $client; + private ?Invoice $invoice = null; // constructor injection better public function __construct( private ClientService $model, private InvoiceService $invoiceModel, + private InvoiceFormFactory $invoiceFormFactory, ) { parent::__construct(); } @@ -40,7 +41,6 @@ public function actionDetail(int $id): void if ($client === null) { $this->flashMessage('Klient nebyl nalezen.', 'danger'); $this->redirect('Homepage:'); - return; // to be sure } $this->client = $client; @@ -51,103 +51,48 @@ public function renderDetail(): void { $this->template->client = $this->client; $this->template->invoices = $this->invoiceModel->getAllByClient($this->client); - - // now we have correct data type - /** @var UI\Form $invoiceForm */ - $invoiceForm = $this['invoiceForm']; - $invoiceForm->setDefaults([ - 'issueDate' => date('Y-m-d'), - 'dueDate' => date('Y-m-d'), - ]); - } - - - protected function createComponentInvoiceForm(): UI\Form - { - // TODO: translate - $form = new UI\Form; - $form->addProtection('Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'); - - $form->addText('amount') - ->setRequired('Zadejte prosím částku.') - ->addRule(UI\Form::NUMERIC, 'Zadejte prosím číslo.'); - - $form->addText('issueDate') - ->setHtmlType('date') - ->setRequired('Zvolte prosím datum vytavení'); - - $form->addText('dueDate') - ->setHtmlType('date') - ->setRequired('Zvolte prosím datum splatnosti'); - - $form->addSubmit('submit'); - - $form->onSuccess[] = [$this, 'invoiceFormSucceeded']; - $form->onValidate[] = [$this, 'invoiceFormValidate']; - $form->onError[] = function (): void { - if ($this->isAjax()) { - $this->redrawControl('invoiceForm'); - } - }; - - return $form; } /** - * @throws InvalidLinkException * @throws AbortException */ - public function invoiceFormValidate(UI\Form $form, stdClass $data): void + public function handleAddPayment(int $invoiceId): void { - $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); - - if ($issueDate === false) { - /** @var Nette\Forms\Controls\TextInput $issueDateInput */ - $issueDateInput = $form['issueDate']; - $issueDateInput->addError('Zadejte prosím platné datum.'); - } - - $dueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); + $invoice = $this->invoiceModel->get($invoiceId); - if ($dueDate === false) { - /** @var Nette\Forms\Controls\TextInput $dueDate */ - $dueDateInput = $form['dueDate']; - $dueDateInput->addError('Zadejte prosím platné datum.'); - } - - // clear, not exactly necessary - unset($issueDate, $dueDate); - - if ($this->isAjax() === false) { + if ($invoice === null) { + $this->flashMessage('Faktura s tímto ID neexistuje.', 'success'); $this->redirect('this'); - return; } - $this->redrawControl('invoiceForm'); - $this->redrawControl('invoicesTable'); + $this->invoice = $invoice; + $this->redrawControl('invoiceFormSnippet'); } - /** - * @throws InvalidLinkException - * @throws AbortException - */ - public function invoiceFormSucceeded(UI\Form $form, stdClass $data): void + public function createComponentInvoiceForm(): InvoiceForm { - $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); - $dueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->dueDate); + $invoiceFormComponent = $this->invoiceFormFactory->create($this->client, $this->invoice); - $this->invoiceModel->create($this->client, $data->amount, $issueDate, $dueDate); + /** @var UI\Form $invoiceForm */ + $invoiceForm = $invoiceFormComponent->getComponent('invoiceForm'); + $invoiceForm->onValidate[] = fn () => $this->redrawControl('invoicesTable'); + $invoiceForm->onSuccess[] = function (): void { + $this->payload->postGet = true; + $this->payload->url = $this->link('this'); + $this->redrawControl('invoicesTable'); + }; - if ($this->isAjax() === false) { - $this->redirect('this'); - } + /** @var UI\Form $paymentForm */ + $paymentForm = $invoiceFormComponent->getComponent('paymentForm'); + $paymentForm->onSuccess[] = function () use($invoiceFormComponent): void { + $this->payload->postGet = true; + $this->payload->url = $this->link('this'); + $this->redrawControl('invoicesTable'); + $this->redrawControl('invoiceFormSnippet'); + }; - $form->reset(); - $this->payload->postGet = true; - $this->payload->url = $this->link('this'); - $this->redrawControl('invoiceForm'); - $this->redrawControl('invoicesTable'); + return $invoiceFormComponent; } } diff --git a/app/Presenters/templates/Client/detail.latte b/app/Presenters/templates/Client/detail.latte index f26f04c..03060f8 100644 --- a/app/Presenters/templates/Client/detail.latte +++ b/app/Presenters/templates/Client/detail.latte @@ -8,30 +8,9 @@

Faktury klienta {$client->getFirstName()} {$client->getLastName()} ({$client->getIc()})


-

Nová faktura

-
-
- {include formErrors form => $form} -
-
- - - {include inputErrors input => $form[amount]} -
-
- - - {include inputErrors input => $form[issueDate]} -
-
- - - {include inputErrors input => $form[dueDate]} -
-
- -
-
+{snippet invoiceFormSnippet} + {control invoiceForm} +{/snippet}
@@ -41,11 +20,12 @@ Částka Datum vystavení Datum splatnosti + Akce - {$invoice->getAmount()|number:2, ',', ' '} Kč + {$invoice->getAmount()->getAmount() / 100|number:2, ',', ' '} Kč {$invoice->getIssueDate()|date:'j. n. Y'} {if $invoice->getDueDate() !== null} @@ -54,6 +34,9 @@ - {/if} + + Přidat platbu + diff --git a/composer.json b/composer.json index 1bff0f4..bbd9961 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "latte/latte": "^2.10", "tracy/tracy": "^2.9", "contributte/webpack": "^2.1", - "nettrine/orm": "^0.8.3" + "nettrine/orm": "^0.8.3", + "moneyphp/money": "^3.3" }, "require-dev": { "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 716d1f2..19883c1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "17f777a9f3a73d4b6070d2ffd6cebf0d", + "content-hash": "150b0631fc6cef4cbd52c7ee5cec00bd", "packages": [ { "name": "contributte/di", @@ -1237,6 +1237,92 @@ }, "time": "2022-04-07T13:21:53+00:00" }, + { + "name": "moneyphp/money", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/moneyphp/money.git", + "reference": "0dc40e3791c67e8793e3aa13fead8cf4661ec9cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/moneyphp/money/zipball/0dc40e3791c67e8793e3aa13fead8cf4661ec9cd", + "reference": "0dc40e3791c67e8793e3aa13fead8cf4661ec9cd", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.6" + }, + "require-dev": { + "cache/taggable-cache": "^0.4.0", + "doctrine/instantiator": "^1.0.5", + "ext-bcmath": "*", + "ext-gmp": "*", + "ext-intl": "*", + "florianv/exchanger": "^1.0", + "florianv/swap": "^3.0", + "friends-of-phpspec/phpspec-code-coverage": "^3.1.1 || ^4.3", + "moneyphp/iso-currencies": "^3.2.1", + "php-http/message": "^1.4", + "php-http/mock-client": "^1.0.0", + "phpspec/phpspec": "^3.4.3", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.18 || ^8.5", + "psr/cache": "^1.0", + "symfony/phpunit-bridge": "^4" + }, + "suggest": { + "ext-bcmath": "Calculate without integer limits", + "ext-gmp": "Calculate without integer limits", + "ext-intl": "Format Money objects with intl", + "florianv/exchanger": "Exchange rates library for PHP", + "florianv/swap": "Exchange rates library for PHP", + "psr/cache-implementation": "Used for Currency caching" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Money\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathias Verraes", + "email": "mathias@verraes.net", + "homepage": "http://verraes.net" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "Frederik Bosch", + "email": "f.bosch@genkgo.nl" + } + ], + "description": "PHP implementation of Fowler's Money pattern", + "homepage": "http://moneyphp.org", + "keywords": [ + "Value Object", + "money", + "vo" + ], + "support": { + "issues": "https://github.com/moneyphp/money/issues", + "source": "https://github.com/moneyphp/money/tree/v3.3.3" + }, + "time": "2022-09-21T07:43:36+00:00" + }, { "name": "nette/application", "version": "v3.1.5", diff --git a/config/common.neon b/config/common.neon index 8a8fb79..3e25030 100644 --- a/config/common.neon +++ b/config/common.neon @@ -67,6 +67,9 @@ services: - Netvor\Invoice\Model\ClientService - Netvor\Invoice\Model\InvoiceService + # FORMS + - Netvor\Invoice\Form\InvoiceForm\InvoiceFormFactory + - Netvor\Invoice\Router\RouterFactory::createRouter diff --git a/docker-compose.yml b/docker-compose.yml index d0a3d19..4be38ff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,7 +57,7 @@ services: - webpack volumes: - .:/app - - vendor:/app/vendor + - ./vendor:/app/vendor - composer:/home/docker-container-user/.composer environment: - NETTE_DEBUG diff --git a/migrations/Version20221019180709.php b/migrations/Version20221019180709.php new file mode 100644 index 0000000..1e554d5 --- /dev/null +++ b/migrations/Version20221019180709.php @@ -0,0 +1,73 @@ +hasTable('invoice') === true) { + $table = $schema->getTable('invoice'); + + if ($table->hasColumn('amount') === true) { + // TODO: backup before executing + $this->connection->executeQuery('UPDATE invoice SET amount = amount * 100'); // migrate to cents + $table->getColumn('amount')->setType(new IntegerType); + } + } + + if ($schema->hasTable('payment') === false) { + $table = $schema->createTable('payment'); + $table->addColumn('id', Types::INTEGER) + ->setAutoincrement(true); + $table->addColumn('invoice_id', Types::INTEGER)->setNotnull(true); + $table->addColumn('amount', Types::INTEGER)->setNotnull(true); + $table->addColumn('created_at', Types::DATETIME_IMMUTABLE)->setNotnull(true); + $table->addForeignKeyConstraint('invoice', ['invoice_id'], ['id']); + $table->setPrimaryKey(['id']); + } + } + + + public function down(Schema $schema): void + { + if ($schema->hasTable('invoice') === true) { + $table = $schema->getTable('invoice'); + + if ($table->hasColumn('amount') === true) { + // TODO: backup before executing + $table->getColumn('amount')->setType(new DecimalType)->setOptions(['scale' => 2, 'precision' => 12]); + $this->connection->executeQuery('UPDATE invoice SET amount = amount / 100'); // migrate back to deciaml + } + } + + if ($schema->hasTable('payment') === true) { + // TODO: backup table before executing + $schema->dropTable('payment'); + } + } +} From 7887ac411af71b2778e370b5ff3266e9aea69102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Wed, 19 Oct 2022 23:58:16 +0200 Subject: [PATCH 6/9] show paid amount --- app/Presenters/templates/Client/detail.latte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Presenters/templates/Client/detail.latte b/app/Presenters/templates/Client/detail.latte index 03060f8..b23d174 100644 --- a/app/Presenters/templates/Client/detail.latte +++ b/app/Presenters/templates/Client/detail.latte @@ -18,6 +18,7 @@ Částka + Zaplaceno Datum vystavení Datum splatnosti Akce @@ -26,6 +27,7 @@ {$invoice->getAmount()->getAmount() / 100|number:2, ',', ' '} Kč + {$invoice->getPaidAmount() / 100|number:2, ',', ' '} Kč {$invoice->getIssueDate()|date:'j. n. Y'} {if $invoice->getDueDate() !== null} @@ -35,7 +37,9 @@ {/if} - Přidat platbu + {if (int)$invoice->getAmount()->getAmount() !== $invoice->getPaidAmount()} + Přidat platbu + {/if} From 02afef4c25d9271726c0e440c67d8e26142221e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Thu, 20 Oct 2022 08:11:13 +0200 Subject: [PATCH 7/9] unpaid invoices --- app/Form/InvoiceForm/InvoiceForm.php | 7 +- app/Model/ARESRegistrySubjectFinder.php | 22 + app/Model/DTO/Subject.php | 10 + app/Model/IRegistrySubjectFinder.php | 12 + app/Model/InvoiceService.php | 37 ++ app/Presenters/ClientPresenter.php | 24 +- app/Presenters/HomepagePresenter.php | 10 +- app/Presenters/templates/Client/detail.latte | 4 + composer.json | 3 +- composer.lock | 659 ++++++++++++++++++- config/common.neon | 1 + 11 files changed, 756 insertions(+), 33 deletions(-) create mode 100644 app/Model/ARESRegistrySubjectFinder.php create mode 100644 app/Model/DTO/Subject.php create mode 100644 app/Model/IRegistrySubjectFinder.php diff --git a/app/Form/InvoiceForm/InvoiceForm.php b/app/Form/InvoiceForm/InvoiceForm.php index cdad192..8b3dffb 100644 --- a/app/Form/InvoiceForm/InvoiceForm.php +++ b/app/Form/InvoiceForm/InvoiceForm.php @@ -136,10 +136,7 @@ protected function createComponentInvoiceForm(): Form } - /** - * @throws AbortException - */ - protected function invoiceFormValidate(Form $form, stdClass $data): void + public function invoiceFormValidate(Form $form, stdClass $data): void { // TODO: translate if (Validators::isNumeric($data->amount) === false) { @@ -153,7 +150,7 @@ protected function invoiceFormValidate(Form $form, stdClass $data): void /** * @throws AbortException */ - protected function invoiceFormSuccess(Form $form, stdClass $data): void + public function invoiceFormSuccess(Form $form, stdClass $data): void { $issueDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->issueDate); diff --git a/app/Model/ARESRegistrySubjectFinder.php b/app/Model/ARESRegistrySubjectFinder.php new file mode 100644 index 0000000..e8d83bd --- /dev/null +++ b/app/Model/ARESRegistrySubjectFinder.php @@ -0,0 +1,22 @@ +entityManager->createQueryBuilder(); + $sumPaymentQuery->select('SUM(p1.amount)') + ->from(Payment::class, 'p1') + ->where($sumPaymentQuery->expr()->eq('p1.invoice', 'i')); + + $countPaymentQuery = $this->entityManager->createQueryBuilder(); + $countPaymentQuery->select('COUNT(p2.amount)') + ->from(Payment::class, 'p2') + ->where($countPaymentQuery->expr()->eq('p2.invoice', 'i')); + + $qb = $this->entityManager->createQueryBuilder(); + $qb->select('i') + ->from(Invoice::class, 'i') + ->where('' . $qb->expr()->lte('i.dueDate', ':today')) + ->andWhere($qb->expr()->eq('i.client', ':client') . '') + ->andWhere( + $qb->expr()->orX( + $qb->expr()->lt('(' . $sumPaymentQuery->getDQL() . ')', 'i.amount'), + $qb->expr()->eq('(' . $countPaymentQuery->getDQL() . ')', 0), + ), + ); + + $qb->setParameter('client', $client); + $qb->setParameter('today', new DateTime); + + return $qb->getQuery()->getResult(); + } + + /** * @return Entities\Invoice[] */ diff --git a/app/Presenters/ClientPresenter.php b/app/Presenters/ClientPresenter.php index 001e296..530fd9d 100644 --- a/app/Presenters/ClientPresenter.php +++ b/app/Presenters/ClientPresenter.php @@ -49,11 +49,33 @@ public function actionDetail(int $id): void public function renderDetail(): void { + $showUnpaid = (bool) $this->getParameter('showUnpaid'); + + $this->template->showUnpaid = $showUnpaid; $this->template->client = $this->client; + + if ($showUnpaid === true) { + $this->template->invoices = $this->invoiceModel->findUnpaidInvoicesByClient($this->client); + return; + } + $this->template->invoices = $this->invoiceModel->getAllByClient($this->client); } + public function handleShowUnpaid(bool $showUnpaid): void + { + $this->template->invoices = $showUnpaid === true + ? $this->invoiceModel->findUnpaidInvoicesByClient($this->client) + : $this->invoiceModel->getAllByClient($this->client); + + if ($this->isAjax() === true) { + $this->redrawControl('invoicesTable'); + $this->redrawControl('showUnpaid'); + } + } + + /** * @throws AbortException */ @@ -86,7 +108,7 @@ public function createComponentInvoiceForm(): InvoiceForm /** @var UI\Form $paymentForm */ $paymentForm = $invoiceFormComponent->getComponent('paymentForm'); - $paymentForm->onSuccess[] = function () use($invoiceFormComponent): void { + $paymentForm->onSuccess[] = function (): void { $this->payload->postGet = true; $this->payload->url = $this->link('this'); $this->redrawControl('invoicesTable'); diff --git a/app/Presenters/HomepagePresenter.php b/app/Presenters/HomepagePresenter.php index 8ca29c6..64c72b8 100644 --- a/app/Presenters/HomepagePresenter.php +++ b/app/Presenters/HomepagePresenter.php @@ -7,13 +7,19 @@ use Nette; use Nette\Application\UI; use Netvor\Invoice\Model\ClientService; +use Netvor\Invoice\Model\IRegistrySubjectFinder; use Netvor\Invoice\Model\Structures\ClientData; final class HomepagePresenter extends UI\Presenter { - /** @inject */ - public ClientService $model; + // pass by interface, not by implementation + public function __construct( + private ClientService $model, +// private IRegistrySubjectFinder $subjectFinder, + ) { + parent::__construct(); + } public function renderDefault(): void diff --git a/app/Presenters/templates/Client/detail.latte b/app/Presenters/templates/Client/detail.latte index b23d174..2fc0213 100644 --- a/app/Presenters/templates/Client/detail.latte +++ b/app/Presenters/templates/Client/detail.latte @@ -14,6 +14,10 @@
+{snippet showUnpaid} + {if $showUnpaid === true}Zobrazit všechny{else}Zobrazit nezaplacené{/if} +{/snippet} + diff --git a/composer.json b/composer.json index bbd9961..7c914ee 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "tracy/tracy": "^2.9", "contributte/webpack": "^2.1", "nettrine/orm": "^0.8.3", - "moneyphp/money": "^3.3" + "moneyphp/money": "^3.3", + "contributte/guzzlette": "^3.2" }, "require-dev": { "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 19883c1..67bf5cf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "150b0631fc6cef4cbd52c7ee5cec00bd", + "content-hash": "2418312af7f2543fceaa78bf6b978040", "packages": [ { "name": "contributte/di", @@ -77,6 +77,82 @@ }, "time": "2020-12-26T17:02:42+00:00" }, + { + "name": "contributte/guzzlette", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/contributte/guzzlette.git", + "reference": "87a6da5c48d70941ec54b330f5373ac884bb8015" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/contributte/guzzlette/zipball/87a6da5c48d70941ec54b330f5373ac884bb8015", + "reference": "87a6da5c48d70941ec54b330f5373ac884bb8015", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.3.3|^7.0", + "nette/di": "~3.0.0", + "php": ">=7.2", + "tracy/tracy": "^2.8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "ninjify/nunjuck": "^0.4", + "ninjify/qa": "^0.12", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-nette": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Contributte\\Guzzlette\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Milan Felix Šulc", + "homepage": "https://f3l1x.io" + }, + { + "name": "Martin Macho", + "email": "matyxcz@gmail.com" + } + ], + "description": "Guzzle integration into Nette Framework", + "homepage": "https://github.com/contributte/guzzlette", + "keywords": [ + "Guzzle", + "nette" + ], + "support": { + "issues": "https://github.com/contributte/guzzlette/issues", + "source": "https://github.com/contributte/guzzlette/tree/v3.2.3" + }, + "funding": [ + { + "url": "https://contributte.org/partners.html", + "type": "custom" + }, + { + "url": "https://github.com/f3l1x", + "type": "github" + } + ], + "time": "2022-09-13T12:44:13+00:00" + }, { "name": "contributte/webpack", "version": "2.1.1", @@ -1153,6 +1229,337 @@ }, "time": "2022-04-06T14:59:40+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", + "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9 || ^2.4", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2022-08-28T15:39:27+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "b94b2807d85443f9719887892882d0329d1e2598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", + "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2022-08-28T14:55:35+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/69568e4293f4fa993f3b0e51c9723e1e17c41379", + "reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.4.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2022-08-28T14:45:39+00:00" + }, { "name": "latte/latte", "version": "v2.11.1", @@ -2858,6 +3265,210 @@ }, "time": "2021-11-05T16:47:00+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, { "name": "symfony/console", "version": "v5.4.7", @@ -2959,7 +3570,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -3006,7 +3617,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -3189,16 +3800,16 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + "reference": "219aa369ceff116e673852dce47c3a41794c14bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd", "shasum": "" }, "require": { @@ -3210,7 +3821,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3253,7 +3864,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" }, "funding": [ { @@ -3269,20 +3880,20 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", "shasum": "" }, "require": { @@ -3297,7 +3908,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3336,7 +3947,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" }, "funding": [ { @@ -3352,20 +3963,20 @@ "type": "tidelift" } ], - "time": "2021-11-30T18:21:41+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.25.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" + "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", + "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", "shasum": "" }, "require": { @@ -3374,7 +3985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.26-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3412,7 +4023,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" }, "funding": [ { @@ -3428,7 +4039,7 @@ "type": "tidelift" } ], - "time": "2021-05-27T09:17:38+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-php73", diff --git a/config/common.neon b/config/common.neon index 3e25030..15b0c93 100644 --- a/config/common.neon +++ b/config/common.neon @@ -66,6 +66,7 @@ services: - Netvor\Invoice\Mails\MailService(templateDir: %email.templateDir%, defaultFromEmail: %email.from%) - Netvor\Invoice\Model\ClientService - Netvor\Invoice\Model\InvoiceService + - Netvor\Invoice\Model\ARESRegistrySubjectFinder # FORMS - Netvor\Invoice\Form\InvoiceForm\InvoiceFormFactory From 44c0ad43b1b9f82bbc61e65ca09c920d8d8a3b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Thu, 20 Oct 2022 08:11:23 +0200 Subject: [PATCH 8/9] cs fix --- app/Presenters/HomepagePresenter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Presenters/HomepagePresenter.php b/app/Presenters/HomepagePresenter.php index 64c72b8..5218dca 100644 --- a/app/Presenters/HomepagePresenter.php +++ b/app/Presenters/HomepagePresenter.php @@ -7,7 +7,6 @@ use Nette; use Nette\Application\UI; use Netvor\Invoice\Model\ClientService; -use Netvor\Invoice\Model\IRegistrySubjectFinder; use Netvor\Invoice\Model\Structures\ClientData; From 43276903d552267812512b2693c50b98f5d1ae6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20=C4=8Cuba?= Date: Thu, 20 Oct 2022 08:18:18 +0200 Subject: [PATCH 9/9] remove unused guzzzlete since ARES implementation not done --- composer.json | 3 +- composer.lock | 613 +------------------------------------------------- 2 files changed, 2 insertions(+), 614 deletions(-) diff --git a/composer.json b/composer.json index 7c914ee..bbd9961 100644 --- a/composer.json +++ b/composer.json @@ -28,8 +28,7 @@ "tracy/tracy": "^2.9", "contributte/webpack": "^2.1", "nettrine/orm": "^0.8.3", - "moneyphp/money": "^3.3", - "contributte/guzzlette": "^3.2" + "moneyphp/money": "^3.3" }, "require-dev": { "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 67bf5cf..a6a506b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2418312af7f2543fceaa78bf6b978040", + "content-hash": "150b0631fc6cef4cbd52c7ee5cec00bd", "packages": [ { "name": "contributte/di", @@ -77,82 +77,6 @@ }, "time": "2020-12-26T17:02:42+00:00" }, - { - "name": "contributte/guzzlette", - "version": "v3.2.3", - "source": { - "type": "git", - "url": "https://github.com/contributte/guzzlette.git", - "reference": "87a6da5c48d70941ec54b330f5373ac884bb8015" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/contributte/guzzlette/zipball/87a6da5c48d70941ec54b330f5373ac884bb8015", - "reference": "87a6da5c48d70941ec54b330f5373ac884bb8015", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.3.3|^7.0", - "nette/di": "~3.0.0", - "php": ">=7.2", - "tracy/tracy": "^2.8.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "ninjify/nunjuck": "^0.4", - "ninjify/qa": "^0.12", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-nette": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Contributte\\Guzzlette\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Milan Felix Šulc", - "homepage": "https://f3l1x.io" - }, - { - "name": "Martin Macho", - "email": "matyxcz@gmail.com" - } - ], - "description": "Guzzle integration into Nette Framework", - "homepage": "https://github.com/contributte/guzzlette", - "keywords": [ - "Guzzle", - "nette" - ], - "support": { - "issues": "https://github.com/contributte/guzzlette/issues", - "source": "https://github.com/contributte/guzzlette/tree/v3.2.3" - }, - "funding": [ - { - "url": "https://contributte.org/partners.html", - "type": "custom" - }, - { - "url": "https://github.com/f3l1x", - "type": "github" - } - ], - "time": "2022-09-13T12:44:13+00:00" - }, { "name": "contributte/webpack", "version": "2.1.1", @@ -1229,337 +1153,6 @@ }, "time": "2022-04-06T14:59:40+00:00" }, - { - "name": "guzzlehttp/guzzle", - "version": "7.5.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.5", - "guzzlehttp/psr7": "^1.9 || ^2.4", - "php": "^7.2.5 || ^8.0", - "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" - }, - "provide": { - "psr/http-client-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "suggest": { - "ext-curl": "Required for CURL handler support", - "ext-intl": "Required for Internationalized Domain Name (IDN) support", - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "7.5-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "psr-18", - "psr-7", - "rest", - "web service" - ], - "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.5.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", - "type": "tidelift" - } - ], - "time": "2022-08-28T15:39:27+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "1.5.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", - "type": "tidelift" - } - ], - "time": "2022-08-28T14:55:35+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "2.4.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/69568e4293f4fa993f3b0e51c9723e1e17c41379", - "reference": "69568e4293f4fa993f3b0e51c9723e1e17c41379", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.4.1" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "time": "2022-08-28T14:45:39+00:00" - }, { "name": "latte/latte", "version": "v2.11.1", @@ -3265,210 +2858,6 @@ }, "time": "2021-11-05T16:47:00+00:00" }, - { - "name": "psr/http-client", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client/tree/master" - }, - "time": "2020-06-29T06:28:15+00:00" - }, - { - "name": "psr/http-factory", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" - }, - "time": "2019-04-30T12:38:16+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/master" - }, - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" - }, { "name": "symfony/console", "version": "v5.4.7",