mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
19080933b6
Shift automatically applies the Laravel coding style - which uses the PSR-2 coding style as a base with some minor additions. You may customize the code style applied by adding a [PHP CS Fixer][1] or [PHP CodeSniffer][2] ruleset to your project root. Feel free to use [Shift's Laravel ruleset][3] to help you get started. For more information on customizing the code style applied by Shift, [watch this short video][4]. [1]: https://github.com/FriendsOfPHP/PHP-CS-Fixer [2]: https://github.com/squizlabs/PHP_CodeSniffer [3]: https://gist.github.com/laravel-shift/cab527923ed2a109dda047b97d53c200 [4]: https://laravelshift.com/videos/shift-code-style
141 lines
3.7 KiB
PHP
141 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Utils;
|
|
|
|
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
|
|
|
|
class CssInlinerPlugin implements \Swift_Events_SendListener
|
|
{
|
|
/**
|
|
* @var CssToInlineStyles
|
|
*/
|
|
protected $converter;
|
|
|
|
/**
|
|
* @var string[]
|
|
*/
|
|
protected $cssCache;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $options;
|
|
|
|
/**
|
|
* @param array $options options defined in the configuration file.
|
|
*/
|
|
public function __construct(array $options)
|
|
{
|
|
$this->converter = new CssToInlineStyles();
|
|
$this->options = $options;
|
|
}
|
|
|
|
/**
|
|
* @param \Swift_Events_SendEvent $evt
|
|
*/
|
|
public function beforeSendPerformed(\Swift_Events_SendEvent $evt)
|
|
{
|
|
$message = $evt->getMessage();
|
|
|
|
if ($message->getContentType() === 'text/html'
|
|
|| ($message->getContentType() === 'multipart/alternative' && $message->getBody())
|
|
|| ($message->getContentType() === 'multipart/mixed' && $message->getBody())
|
|
) {
|
|
[$body, $cssResources] = $this->messageSieve($message->getBody());
|
|
$css = $this->concatCss($cssResources);
|
|
$message->setBody($this->converter->convert($body, $css));
|
|
}
|
|
|
|
foreach ($message->getChildren() as $part) {
|
|
if (strpos($part->getContentType(), 'text/html') === 0) {
|
|
[$body, $cssResources] = $this->messageSieve($part->getBody());
|
|
$css = $this->concatCss($cssResources);
|
|
$part->setBody($this->converter->convert($body, $css));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Do nothing
|
|
*
|
|
* @param \Swift_Events_SendEvent $evt
|
|
*/
|
|
public function sendPerformed(\Swift_Events_SendEvent $evt)
|
|
{
|
|
// Do Nothing
|
|
}
|
|
|
|
protected function concatCss(array $cssResources): string
|
|
{
|
|
$output = '';
|
|
foreach ($cssResources as $cssResource) {
|
|
$output .= $this->fetchCss($cssResource);
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
protected function fetchCss(string $filename): string
|
|
{
|
|
if (isset($this->cssCache[$filename])) {
|
|
return $this->cssCache[$filename];
|
|
}
|
|
|
|
$fixedFilename = $filename;
|
|
// Fix relative protocols on hrefs. Assume https.
|
|
if (substr($filename, 0, 2) === '//') {
|
|
$fixedFilename = 'https:'.$filename;
|
|
}
|
|
|
|
$content = file_get_contents($fixedFilename);
|
|
if (! $content) {
|
|
return '';
|
|
}
|
|
|
|
$this->cssCache[$filename] = $content;
|
|
|
|
return $content;
|
|
}
|
|
|
|
protected function messageSieve(string $message): array
|
|
{
|
|
$cssResources = [];
|
|
|
|
// Initialize with config defaults, if any
|
|
if (isset($this->options['css-files'])) {
|
|
$cssResources = $this->options['css-files'];
|
|
}
|
|
|
|
$dom = new \DOMDocument();
|
|
// set error level
|
|
$internalErrors = libxml_use_internal_errors(true);
|
|
|
|
$dom->loadHTML($message);
|
|
|
|
// Restore error level
|
|
libxml_use_internal_errors($internalErrors);
|
|
$link_tags = $dom->getElementsByTagName('link');
|
|
|
|
/** @var \DOMElement $link */
|
|
foreach ($link_tags as $link) {
|
|
if ($link->getAttribute('rel') === 'stylesheet') {
|
|
array_push($cssResources, $link->getAttribute('href'));
|
|
}
|
|
}
|
|
|
|
$link_tags = $dom->getElementsByTagName('link');
|
|
for ($i = $link_tags->length; --$i >= 0;) {
|
|
$link = $link_tags->item($i);
|
|
if ($link->getAttribute('rel') === 'stylesheet') {
|
|
$link->parentNode->removeChild($link);
|
|
}
|
|
}
|
|
|
|
if (count($cssResources)) {
|
|
return [$dom->saveHTML(), $cssResources];
|
|
}
|
|
|
|
return [$message, []];
|
|
}
|
|
}
|