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 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 0
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
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;
0 ignored issues
show
Bug introduced by
The type Application\Utility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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 2
    ) {}
45
46 1
    public function getExtension(): string
47
    {
48 1
        return 'pptx';
49
    }
50
51 2
    public function initialize(Export $export, string $title): void
52
    {
53 2
        $this->needSeparator = false;
54 2
        $this->export = $export;
55 2
        $this->textColor = str_replace('#', 'FF', $export->getTextColor());
56 2
        $this->backgroundColor = str_replace('#', 'FF', $export->getBackgroundColor());
57
58 2
        $this->presentation = new PhpPresentation();
59
60
        // Set a few meta data
61 2
        $properties = $this->presentation->getDocumentProperties();
62 2
        $properties->setCreator(User::getCurrent() ? User::getCurrent()->getLogin() : '');
63 2
        $properties->setLastModifiedBy($this->export->getSite()->getDescription());
64 2
        $properties->setTitle($title);
65 2
        $properties->setSubject('Présentation PowerPoint générée par le système ' . $this->export->getSite()->getDescription());
66 2
        $properties->setDescription("Certaines images sont soumises aux droits d'auteurs. Vous pouvez nous contactez à [email protected] pour plus d'informations.");
67 2
        $properties->setKeywords('Université de Lausanne');
68
69 2
        $slideBackgroundColor = new Slide\Background\Color();
70 2
        $slideBackgroundColor->setColor(new Color($this->backgroundColor));
71
72
        // Define default background color for all slides.
73 2
        array_map(
74 2
            fn (SlideMaster $masterSlide) => $masterSlide->setBackground($slideBackgroundColor),
75 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

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