diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index d9491378..bb76cf62 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -33,6 +33,7 @@ use App\Services\AmountFormatter; use App\Services\Attachments\AttachmentURLGenerator; use App\Services\Attachments\PartPreviewGenerator; use App\Services\EntityURLGenerator; +use App\Services\FAIconGenerator; use App\Services\TreeBuilder; use Doctrine\ORM\QueryBuilder; use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider; @@ -58,7 +59,8 @@ class PartsDataTable implements DataTableTypeInterface public function __construct(EntityURLGenerator $urlGenerator, TranslatorInterface $translator, TreeBuilder $treeBuilder, AmountFormatter $amountFormatter, - PartPreviewGenerator $previewGenerator, AttachmentURLGenerator $attachmentURLGenerator) + PartPreviewGenerator $previewGenerator, AttachmentURLGenerator $attachmentURLGenerator, + FAIconGenerator $FAIconGenerator) { $this->urlGenerator = $urlGenerator; $this->translator = $translator; diff --git a/src/Services/FAIconGenerator.php b/src/Services/FAIconGenerator.php new file mode 100644 index 00000000..820e117d --- /dev/null +++ b/src/Services/FAIconGenerator.php @@ -0,0 +1,88 @@ + ['pdf'], + 'fa-file-image' => Attachment::PICTURE_EXTS, + 'fa-file-alt' => ['txt', 'md', 'rtf', 'log', 'rst', 'tex'], + 'fa-file-csv' => ['csv'], + 'fa-file-word' => ['doc', 'docx', 'odt'], + 'fa-file-archive' => ['zip', 'rar', 'bz2', 'tar', '7z', 'gz'], + 'fa-file-audio' => ['mp3', 'wav', 'aac', 'm4a', 'wma'], + 'fa-file-powerpoint' => ['ppt', 'pptx', 'odp', 'pps', 'key'], + 'fa-file-excel' => ['xls', 'xlr', 'xlsx', 'ods'], + 'fa-file-code' => ['php', 'xml', 'html', 'js', 'ts', 'htm', 'c', 'cpp'], + 'fa-file-video' => ['webm', 'avi', 'mp4', 'mkv', 'wmv'], + ]; + + /** + * Gets the Font awesome icon class for a file with the specified extension. + * For example 'pdf' gives you 'fa-file-pdf' + * @param string $extension The file extension (without dot). Must be ASCII chars only! + * @return string The fontawesome class with leading 'fa-' + */ + public function fileExtensionToFAType(string $extension) : string + { + if ($extension === '') { + throw new \InvalidArgumentException('You must specify an extension!'); + } + //Normalize file extension + $extension = strtolower($extension); + foreach (self::EXT_MAPPING as $fa => $exts) { + if (in_array($extension, $exts, true)) { + return $fa; + } + } + + // When the extension is not found in the mapping array, we return the generic icon + return 'fa-file'; + } + + /** + * Returns HTML code to show the given fontawesome icon. + * E.g. + * @param string $icon_class The icon which should be shown (e.g. fa-file-text) + * @param string $style The style of the icon 'fas' + * @param string $options Any other css class attributes like size, etc. + * @return string The final html + */ + public function generateIconHTML(string $icon_class, string $style = 'fas', string $options = '') : string + { + //XSS protection + $icon_class = htmlspecialchars($icon_class); + $style = htmlspecialchars($style); + $options = htmlspecialchars($options); + + return sprintf( + '', + $style, + $icon_class, + $options + ); + } +} \ No newline at end of file diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 8023f067..3249784d 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -27,6 +27,7 @@ use App\Entity\PriceInformations\Currency; use App\Services\AmountFormatter; use App\Services\Attachments\AttachmentURLGenerator; use App\Services\EntityURLGenerator; +use App\Services\FAIconGenerator; use App\Services\MarkdownParser; use App\Services\MoneyFormatter; use App\Services\SIFormatter; @@ -47,12 +48,14 @@ class AppExtension extends AbstractExtension protected $siformatter; protected $amountFormatter; protected $attachmentURLGenerator; + protected $FAIconGenerator; public function __construct(EntityURLGenerator $entityURLGenerator, MarkdownParser $markdownParser, SerializerInterface $serializer, TreeBuilder $treeBuilder, MoneyFormatter $moneyFormatter, SIFormatter $SIFormatter, AmountFormatter $amountFormatter, - AttachmentURLGenerator $attachmentURLGenerator) + AttachmentURLGenerator $attachmentURLGenerator, + FAIconGenerator $FAIconGenerator) { $this->entityURLGenerator = $entityURLGenerator; $this->markdownParser = $markdownParser; @@ -62,6 +65,7 @@ class AppExtension extends AbstractExtension $this->siformatter = $SIFormatter; $this->amountFormatter = $amountFormatter; $this->attachmentURLGenerator = $attachmentURLGenerator; + $this->FAIconGenerator = $FAIconGenerator; } public function getFilters() @@ -90,6 +94,7 @@ class AppExtension extends AbstractExtension return [ new TwigFunction('generateTreeData', [$this, 'treeData']), new TwigFunction('attachment_thumbnail', [$this->attachmentURLGenerator, 'getThumbnailURL']), + new TwigFunction('ext_to_fa_icon', [$this->FAIconGenerator, 'fileExtensionToFAType']), ]; } diff --git a/templates/helper.twig b/templates/helper.twig index c769f70e..10775b2b 100644 --- a/templates/helper.twig +++ b/templates/helper.twig @@ -6,41 +6,13 @@ {% endif %} {% endmacro %} -{% macro file_extension_to_fa_icon(ext) %} - {% if ext in ['jpeg', 'jpg', 'gif', 'png', 'tiff', 'tif', 'webp', 'bmp', 'svg'] %} {# Images #} - fa-file-image - {% elseif ext in ['pdf'] %} {# PDFs #} - fa-file-pdf - {% elseif ext in ['txt', 'md', 'rtf'] %} {# Text files #} - fa-file-alt - {% elseif ext in ['csv'] %} {# CSV files #} - fa-file-csv - {% elseif ext in ['doc', 'docx', 'odt'] %} {# Documents #} - fa-file-word - {% elseif ext in ['zip', 'rar', 'bz2', 'tar', '7z', 'gz'] %} - fa-file-archive - {% elseif ext in ['mp3', 'wav', 'aac', 'm4a', 'wma'] %} - fa-file-audio - {% elseif ext in ['ppt', 'pptx', 'odp'] %} - fa-file-powerpoint - {% elseif ext in ['xls', 'xlsx', 'ods'] %} - fa-file-excel - {% elseif ext in ['php', 'xml', 'html', 'js', 'ts', 'htm', 'c', 'cpp'] %} - fa-file-code - {% elseif ext in ['webm', 'avi', 'mp4', 'mkv', 'wmv'] %} {# Videos#} - fa-file-video - {% else %} - fa-file - {% endif %} -{% endmacro %} - {% macro attachment_icon(attachment, attachment_helper, class = "fa-fw fas fa-3x", link = true) %} {% if not attachment_helper or attachment_helper.fileExisting(attachment) %} {% if attachment.picture %} {% else %} - + {% endif %} {% elseif not attachment_helper.fileExisting(attachment) %} diff --git a/tests/Services/FAIconGeneratorTest.php b/tests/Services/FAIconGeneratorTest.php new file mode 100644 index 00000000..77ba60c0 --- /dev/null +++ b/tests/Services/FAIconGeneratorTest.php @@ -0,0 +1,72 @@ +service = self::$container->get(FAIconGenerator::class); + } + + public function fileExtensionDataProvider() : array + { + return [ + ['pdf', 'fa-file-pdf'], + ['jpeg', 'fa-file-image'], + ['txt', 'fa-file-alt'], + ['doc', 'fa-file-word'], + ['zip', 'fa-file-archive'], + ['php', 'fa-file-code'], + ['tmp', 'fa-file'], + ['fgd', 'fa-file'], + ]; + } + + /** + * @dataProvider fileExtensionDataProvider + */ + public function testFileExtensionToFAType(string $ext, string $expected) + { + $this->assertEquals($expected, $this->service->fileExtensionToFAType($ext)); + } + + public function testGenerateIconHTML() + { + $this->assertEquals('', $this->service->generateIconHTML('fa-file')); + $this->assertEquals('', $this->service->generateIconHTML('fa-file', 'far')); + $this->assertEquals('', $this->service->generateIconHTML('fa-file', 'far', 'fa-2x')); + } +} \ No newline at end of file