Skip to content

Commit

Permalink
Add vcard generator (@Xirdion)
Browse files Browse the repository at this point in the history
- Creates a downloadable vcard from all company data using the following insert tag {company::vcard_url}} @Xirdion
  • Loading branch information
zoglo authored May 10, 2022
2 parents b8b57fb + 2ae83b0 commit ce24a61
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 3 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ Your company information can be displayed using following *insert-tags*.
<td>{{company::countrycode}}</td>
<td>Displays the ISO 639-1 country code from <i>Country</i></td>
</tr>
<tr>
<td>{{company::vcard_url}}</td>
<td>Generates a vcard out of the company data</td>
</tr>
</table>

## Front end modules
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
],
"require":{
"php": "^7.4 || ^8.0",
"contao/core-bundle":"^4.9"
"contao/core-bundle":"^4.9",
"jeroendesloovere/vcard": "^1.7"
},
"require-dev": {
"contao/manager-plugin": "^2.3.1"
Expand Down
16 changes: 15 additions & 1 deletion src/ContaoManager/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Contao\ManagerPlugin\Routing\RoutingPluginInterface;
use Oveleon\ContaoCompanyBundle\ContaoCompanyBundle;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\HttpKernel\KernelInterface;

class Plugin implements BundlePluginInterface
class Plugin implements BundlePluginInterface, RoutingPluginInterface
{
/**
* {@inheritdoc}
Expand All @@ -33,4 +36,15 @@ public function getBundles(ParserInterface $parser): array
->setReplace(['company']),
];
}

/**
* {@inheritdoc}
*/
public function getRouteCollection(LoaderResolverInterface $resolver, KernelInterface $kernel)
{
return $resolver
->resolve(__DIR__.'/../Resources/config/routes.yaml')
->load(__DIR__.'/../Resources/config/routes.yaml')
;
}
}
62 changes: 62 additions & 0 deletions src/Controller/vCardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Oveleon\ContaoCompanyBundle\Controller;

use Contao\PageModel;
use Oveleon\ContaoCompanyBundle\Generator\vCardGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
* @Route(defaults={"_scope" = "frontend"})
*/
class vCardController extends AbstractController
{
private vCardGenerator $generator;

/**
* @param vCardGenerator $generator
*/
public function __construct(vCardGenerator $generator)
{
$this->generator = $generator;
}

/**
* @Route("/company/vcard/download", name="contao_company_vcard_download")
*
* @param Request $request
*
* @return Response
*
* @throws \Exception
*/
public function download(Request $request): Response
{
// Try to load the current contao page
$pageId = (int) $request->query->get('page');
$pageModel = PageModel::findById($pageId);
if (null === $pageModel) {
throw new \Exception('Could not load correct redirect page');
}

try {
// Load all details of the page to have access to rootId
$pageModel->loadDetails();

// Generate the vcard
$vcf = $this->generator
->createCard($pageModel)
->getContent();

$headers = $this->generator->getHeaders();
} catch (\Exception $e) {
$vcf = '';
$headers = [];
}

return new Response($vcf, 200, $headers);
}
}
1 change: 1 addition & 0 deletions src/DependencyInjection/ContaoCompanyExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ public function load(array $mergedConfig, ContainerBuilder $container): void
);

$loader->load('listener.yml');
$loader->load('services.yaml');
}
}
20 changes: 19 additions & 1 deletion src/EventListener/InsertTagsListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@

namespace Oveleon\ContaoCompanyBundle\EventListener;

use Contao\PageModel;
use Contao\System;
use Contao\StringUtil;
use Contao\CoreBundle\Framework\ContaoFramework;
use Oveleon\ContaoCompanyBundle\Company;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;

/**
* Handles insert tags for company details.
Expand All @@ -35,9 +38,14 @@ class InsertTagsListener
*/
private $framework;

public function __construct(ContaoFramework $framework)
private RouterInterface $router;
private RequestStack $requestStack;

public function __construct(ContaoFramework $framework, RouterInterface $router, RequestStack $requestStack)
{
$this->framework = $framework;
$this->router = $router;
$this->requestStack = $requestStack;
}

/**
Expand Down Expand Up @@ -155,6 +163,16 @@ private function replaceCompanyInsertTags($insertTag, $field)
return $strCountry;
case 'countrycode':
return Company::get('country');
case 'vcard_url':
$pageId = 0;
$request = $this->requestStack->getCurrentRequest();
if (null !== $request) {
/** @var PageModel $page */
$page = $request->attributes->get('pageModel');
$pageId = $page->id;
}

return $this->router->generate('contao_company_vcard_download', ['page' => $pageId]);
}

return Company::get($field);
Expand Down
166 changes: 166 additions & 0 deletions src/Generator/vCardGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

namespace Oveleon\ContaoCompanyBundle\Generator;

use Contao\FilesModel;
use Contao\PageModel;
use Contao\System;
use JeroenDesloovere\VCard\VCard;
use Oveleon\ContaoCompanyBundle\Company;
use Symfony\Component\Filesystem\Path;

class vCardGenerator
{
private ?VCard $vCard;
private Company $company;

public function __construct()
{
$this->vCard = null;
}

/**
* Generate a vcard with the given company values.
*
* @param PageModel $pageModel
*
* @return $this
*/
public function createCard(PageModel $pageModel): self
{
// Init company with current page model
$this->company = new Company();
$this->company->initialize($pageModel, null, null);

// Generate the vcard
$this->vCard = new VCard();
$this
->addName()
->addCompany()
->addAddress()
->addEmail()
->addPhone()
->addFax()
->addLogo()
;

return $this;
}

/**
* Get the content of the vcard as string.
*
* @return string
*
* @throws \Exception
*/
public function getContent(): string
{
if (null === $this->vCard) {
throw new \Exception('You must create a v-card first!');
}

return $this->vCard->getOutput();
}

/**
* Get the correct headers to be able to download the vcard.
*
* @return array
*/
public function getHeaders(): array
{
return $this->vCard->getHeaders(true);
}

private function addName(): self
{
$this->vCard->addName($this->company::get('name'));

return $this;
}

private function addCompany(): self
{
$this->vCard->addCompany($this->company::get('name'));

return $this;
}

private function addAddress(): self
{
$street = $this->company::get('street') ?: null;
$city = $this->company::get('city') ?: null;
$state = $this->company::get('state') ?: null;
$zip = $this->company::get('postal') ?: null;
$country = $this->company::get('country') ?: null;
$type = 'WORK;POSTAL';
if (null === $street && null === $city && null === $state && null === $zip && null === $country) {
return $this;
}

$this->vCard->addAddress(null, null, $street, $city, $state, $zip, $country, $type);

return $this;
}

private function addEmail(): self
{
$mail = $this->company::get('email') ?: null;
if (null === $mail) {
$mail = $this->company::get('email2') ?: null;
}
if (null === $mail) {
return $this;
}

$this->vCard->addEmail($mail, 'WORK');

return $this;
}

private function addPhone(): self
{
$phone = $this->company::get('phone') ?: null;
if (null === $phone) {
$phone = $this->company::get('phone2') ?: null;
}
if (null === $phone) {
return $this;
}

$this->vCard->addPhoneNumber($phone, 'WORK');

return $this;
}

private function addFax(): self
{
$fax = $this->company::get('fax') ?: null;
if (null === $fax) {
return $this;
}

$this->vCard->addPhoneNumber($fax, 'FAX');

return $this;
}

private function addLogo(): self
{
$uuid = $this->company::get('logo') ?: null;
if (null === $uuid) {
return $this;
}

$file = FilesModel::findByUuid($uuid);
if (null === $file) {
return $this;
}

$projectDir = System::getContainer()->getParameter('kernel.project_dir');
$this->vCard->addLogo(Path::makeAbsolute($file->path, $projectDir));

return $this;
}
}
2 changes: 2 additions & 0 deletions src/Resources/config/listener.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ services:
class: Oveleon\ContaoCompanyBundle\EventListener\InsertTagsListener
arguments:
- '@contao.framework'
- '@router.default'
- '@request_stack'
tags:
- { name: contao.hook, hook: replaceInsertTags }
public: true
3 changes: 3 additions & 0 deletions src/Resources/config/routes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
company:
resource: '../../Controller'
type: annotation
12 changes: 12 additions & 0 deletions src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
_defaults:
autowire: true

contao_company.vcard.generator:
class: Oveleon\ContaoCompanyBundle\Generator\vCardGenerator

Oveleon\ContaoCompanyBundle\Controller\vCardController:
arguments:
- '@contao_company.vcard.generator'
tags:
- controller.service_arguments

0 comments on commit ce24a61

Please sign in to comment.