Pptx::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 0
c 0
b 0
f 0
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service\Exporter;
6
7
use Application\Model\Card;
8
use Application\Model\Export;
9
use Application\Model\User;
10
use Application\Service\ImageResizer;
11
use Application\Utility;
12
use Imagine\Image\ImagineInterface;
13
use PhpOffice\PhpPresentation\DocumentLayout;
14
use PhpOffice\PhpPresentation\PhpPresentation;
15
use PhpOffice\PhpPresentation\Shape\RichText;
16
use PhpOffice\PhpPresentation\Shape\RichText\Run;
17
use PhpOffice\PhpPresentation\Slide;
18
use PhpOffice\PhpPresentation\Slide\SlideMaster;
19
use PhpOffice\PhpPresentation\Style\Alignment;
20
use PhpOffice\PhpPresentation\Style\Color;
21
use PhpOffice\PhpPresentation\Writer\PowerPoint2007;
22
23
/**
24
 * Export multiples cards as PowerPoint file.
25
 */
26
class Pptx implements Writer
27
{
28
    private const MARGIN = 10;
29
    private const LEGEND_HEIGHT = 75;
30
31
    private bool $needSeparator = false;
32
33
    private string $textColor = Color::COLOR_WHITE;
34
35
    private string $backgroundColor = Color::COLOR_BLACK;
36
37
    private Export $export;
38
39
    private PhpPresentation $presentation;
40
41 2
    public function __construct(
42
        private readonly ImageResizer $imageResizer,
43
        private readonly ImagineInterface $imagine,
44
    ) {
45 2
    }
46
47 1
    public function getExtension(): string
48
    {
49 1
        return 'pptx';
50
    }
51
52 2
    public function initialize(Export $export, string $title): void
53
    {
54 2
        $this->needSeparator = false;
55 2
        $this->export = $export;
56 2
        $this->textColor = str_replace('#', 'FF', $export->getTextColor());
57 2
        $this->backgroundColor = str_replace('#', 'FF', $export->getBackgroundColor());
58
59 2
        $this->presentation = new PhpPresentation();
60
61
        // Set a few meta data
62 2
        $properties = $this->presentation->getDocumentProperties();
63 2
        $properties->setCreator(User::getCurrent() ? User::getCurrent()->getLogin() : '');
64 2
        $properties->setLastModifiedBy($this->export->getSite()->getDescription());
65 2
        $properties->setTitle($title);
66 2
        $properties->setSubject('Présentation PowerPoint générée par le système ' . $this->export->getSite()->getDescription());
67 2
        $properties->setDescription("Certaines images sont soumises aux droits d'auteurs. Vous pouvez nous contactez à [email protected] pour plus d'informations.");
68 2
        $properties->setKeywords('Université de Lausanne');
69
70 2
        $slideBackgroundColor = new Slide\Background\Color();
71 2
        $slideBackgroundColor->setColor(new Color($this->backgroundColor));
72
73
        // Define default background color for all slides.
74 2
        array_map(
75 2
            fn (SlideMaster $masterSlide) => $masterSlide->setBackground($slideBackgroundColor),
76 2
            $this->presentation->getAllMasterSlides(),
0 ignored issues
show
Bug introduced by
It seems like $this->presentation->getAllMasterSlides() can also be of type ArrayObject; however, parameter $array of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

76
            /** @scrutinizer ignore-type */ $this->presentation->getAllMasterSlides(),
Loading history...
77 2
        );
78
79
        // Remove default slide
80 2
        $this->presentation->removeSlideByIndex(0);
81
    }
82
83 2
    public function write(Card $card): void
84
    {
85
        // Skip if no image
86 2
        if (!$card->hasImage() || !is_readable($card->getPath())) {
87 1
            return;
88
        }
89
90
        // Create slide
91 2
        $slide = $this->presentation->createSlide();
92
93 2
        $this->insertImage($slide, $card);
94 2
        $this->insertLegend($slide, $card);
95
    }
96
97 2
    public function finalize(): void
98
    {
99
        // Write to disk
100 2
        $writer = new PowerPoint2007($this->presentation);
101 2
        $writer->save($this->export->getPath());
102
    }
103
104 2
    private function insertImage(Slide $slide, Card $card): void
105
    {
106 2
        $path = $this->imageResizer->resize($card, 1200, false);
107
108
        // Get dimensions
109 2
        $image = $this->imagine->open($path);
110 2
        $size = $image->getSize();
111 2
        $width = $size->getWidth();
112 2
        $height = $size->getHeight();
113 2
        $ratio = $width / $height;
114
115
        // Get available space for our image
116 2
        $availableWidth = $slide->getParent()->getLayout()->getCX(DocumentLayout::UNIT_PIXEL);
117 2
        $availableHeight = $slide->getParent()->getLayout()->getCY(DocumentLayout::UNIT_PIXEL) - self::LEGEND_HEIGHT - 2 * self::MARGIN;
118 2
        $availableRatio = $availableWidth / $availableHeight;
119
120 2
        $shape = $slide->createDrawingShape();
121 2
        $shape->setPath($path);
122
123 2
        if ($ratio > $availableRatio) {
124 2
            $shape->setWidth((int) ($availableWidth - 2 * self::MARGIN));
125 2
            $shape->setOffsetX(self::MARGIN);
126 2
            $shape->setOffsetY((int) (($availableHeight - $shape->getHeight()) / 2 + self::MARGIN));
127
        } else {
128
            $shape->setHeight((int) ($availableHeight - 2 * self::MARGIN));
129
            $shape->setOffsetX((int) (($availableWidth - $shape->getWidth()) / 2 + self::MARGIN));
130
            $shape->setOffsetY(self::MARGIN);
131
        }
132
    }
133
134 2
    private function insertLegend(Slide $slide, Card $card): void
135
    {
136 2
        $shape = $slide->createRichTextShape();
137 2
        $shape->setHeight(self::LEGEND_HEIGHT);
138 2
        $shape->setWidth((int) ($slide->getParent()->getLayout()->getCX(DocumentLayout::UNIT_PIXEL) - 2 * self::MARGIN));
139 2
        $shape->setOffsetX(self::MARGIN);
140 2
        $shape->setOffsetY((int) ($slide->getParent()->getLayout()->getCY(DocumentLayout::UNIT_PIXEL) - self::LEGEND_HEIGHT - self::MARGIN));
141 2
        $shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
142
143 2
        $this->needSeparator = false;
144 2
        foreach ($card->getArtists() as $artist) {
145
            $this->appendText($shape, true, true, false, str_replace(', ', ' ', $artist->getName()));
146
        }
147
148 2
        $this->appendText($shape, true, false, true, $card->getName());
149 2
        $this->appendText($shape, true, false, false, $card->getDating());
150 2
        $shape->createBreak();
151 2
        $this->needSeparator = false;
152 2
        $this->appendText($shape, false, false, false, $card->getMaterial());
153 2
        $this->appendText($shape, false, false, false, $card->getFormat());
154 2
        $this->appendText($shape, false, false, false, $card->getLocality());
155
156 2
        if ($card->getInstitution()) {
157
            $this->appendText($shape, false, false, false, $card->getInstitution()->getName());
158
        }
159
    }
160
161 2
    private function appendText(RichText $shape, bool $big, bool $bold, bool $italic, string $value): void
162
    {
163 2
        if (!$value) {
164 2
            return;
165
        }
166
167 2
        $value = Utility::richTextToPlainText($value);
168
169 2
        if ($this->needSeparator) {
170
            $textRun = $shape->createTextRun(', ');
171
            $this->setFont($textRun, $big, false, false);
172
        }
173
174 2
        $textRun = $shape->createTextRun($value);
175 2
        $this->setFont($textRun, $big, $bold, $italic);
176
177 2
        $this->needSeparator = true;
178
    }
179
180 2
    private function setFont(Run $textRun, bool $big, bool $bold, bool $italic): void
181
    {
182 2
        $font = $textRun->getFont();
183 2
        $font->setSize($big ? 14 : 12);
184 2
        $font->setColor(new Color($this->textColor));
185 2
        $font->setBold($bold);
186 2
        $font->setItalic($italic);
187
    }
188
}
189