]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/IO/PdfMembersCards.php
2c0b65eb5bfd7bd8b3d00dea7c2d70541d8480ad
[galette.git] / galette / lib / Galette / IO / PdfMembersCards.php
1 <?php
2
3 /**
4 * Copyright © 2003-2024 The Galette Team
5 *
6 * This file is part of Galette (https://galette.eu).
7 *
8 * Galette is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Galette is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 namespace Galette\IO;
23
24 use Galette\Core\Preferences;
25 use Galette\Core\PrintLogo;
26 use Analog\Analog;
27 use Galette\Entity\Adherent;
28
29 /**
30 * Member card PDF
31 *
32 * @author Johan Cwiklinski <johan@x-tnd.be>
33 */
34
35 class PdfMembersCards extends Pdf
36 {
37 public const WIDTH = 75;
38 public const HEIGHT = 40;
39 public const COLS = 2;
40 public const ROWS = 6;
41
42 /** @var array<string,float|int> */
43 private array $tcol;
44 /** @var array<string,float|int> */
45 private array $scol;
46 /** @var array<string,float|int> */
47 private array $bcol;
48 /** @var array<string,float|int> */
49 private array $hcol;
50 private int $xorigin;
51 private int $yorigin;
52 private int $wi;
53 private int $he;
54 private int $nbcol;
55 private int $nbrow;
56 private int $hspacing;
57 private int $vspacing;
58 private int $max_text_size;
59 private int $year_font_size;
60 private string $an_cot;
61 private string $abrev;
62 private float $wlogo;
63 private float $hlogo;
64 private string $logofile;
65
66 /**
67 * Main constructor, set creator and author
68 *
69 * @param Preferences $prefs Preferences
70 */
71 public function __construct(Preferences $prefs)
72 {
73 parent::__construct($prefs);
74 $this->setRTL(false);
75 $this->filename = __('cards') . '.pdf';
76 $this->init();
77 }
78 /**
79 * Initialize PDF
80 *
81 * @return void
82 */
83 private function init(): void
84 {
85 // Set document information
86 $this->SetTitle(_T("Member's Cards"));
87 $this->SetSubject(_T("Generated by Galette"));
88 $this->SetKeywords(_T("Cards"));
89
90 // No hearders and footers
91 $this->SetPrintHeader(false);
92 $this->SetPrintFooter(false);
93 $this->setFooterMargin(0);
94 $this->setHeaderMargin(0);
95
96 // Show full page
97 $this->SetDisplayMode('fullpage');
98
99 // Disable Auto Page breaks
100 $this->SetAutoPageBreak(false, 0);
101
102 // Set colors
103 $this->SetDrawColor(160, 160, 160);
104 $this->SetTextColor(0);
105 $this->tcol = $this->colorHex2Dec($this->preferences->pref_card_tcol);
106 $this->scol = $this->colorHex2Dec($this->preferences->pref_card_scol);
107 $this->bcol = $this->colorHex2Dec($this->preferences->pref_card_bcol);
108 $this->hcol = $this->colorHex2Dec($this->preferences->pref_card_hcol);
109
110 // Set margins
111 $this->SetMargins(
112 $this->preferences->pref_card_marges_h,
113 $this->preferences->pref_card_marges_v
114 );
115
116 // Set font
117 $this->SetFont(self::FONT);
118
119 // Set origin
120 // Top left corner
121 $this->xorigin = $this->preferences->pref_card_marges_h;
122 $this->yorigin = $this->preferences->pref_card_marges_v;
123
124 // Card width
125 $this->wi = self::getWidth();
126 // Card heigth
127 $this->he = self::getHeight();
128 // Number of colons
129 $this->nbcol = self::getCols();
130 // Number of rows
131 $this->nbrow = self::getRows();
132 // Spacing between cards
133 $this->hspacing = $this->preferences->pref_card_hspace;
134 $this->vspacing = $this->preferences->pref_card_vspace;
135
136 //maximum size for visible text. May vary with fonts.
137 $this->max_text_size = 80;
138 $this->year_font_size = 8;
139
140 // Get fixed data from preferences
141 $this->an_cot = $this->preferences->pref_card_year;
142 $this->abrev = $this->preferences->pref_card_abrev;
143
144 $print_logo = new PrintLogo();
145 $this->logofile = $print_logo->getPath();
146
147 // Set logo size to max width 30mm (113px) or max height 17mm (64px)
148 $ratio = $print_logo->getWidth() / $print_logo->getHeight();
149 if ($ratio < 1.71) {
150 if ($print_logo->getHeight() > 64) {
151 $this->hlogo = 17;
152 } else {
153 // Convert original pixels size to millimeters
154 $this->hlogo = $print_logo->getHeight() / 3.78;
155 }
156 $this->wlogo = round($this->hlogo * $ratio);
157 } else {
158 if ($print_logo->getWidth() > 113) {
159 $this->wlogo = 30;
160 } else {
161 // Convert original pixels size to millimeters
162 $this->wlogo = $print_logo->getWidth() / 3.78;
163 }
164 $this->hlogo = round($this->wlogo / $ratio);
165 }
166 }
167
168 /**
169 * Draw members cards
170 *
171 * @param array<Adherent> $members Members
172 *
173 * @return void
174 */
175 public function drawCards(array $members): void
176 {
177 $nb_card = 0;
178 foreach ($members as $member) {
179 // Detect page breaks
180 if ($nb_card % ($this->nbcol * $this->nbrow) == 0) {
181 $this->AddPage();
182 }
183
184 // Compute card position on page
185 $col = $nb_card % $this->nbcol;
186 $row = (int)(($nb_card / $this->nbcol)) % $this->nbrow;
187 // Set origin
188 $x0 = $this->xorigin + $col * (round($this->wi) + round($this->hspacing));
189 $y0 = $this->yorigin + $row * (round($this->he) + round($this->vspacing));
190 // Logo X position
191 $xl = round($x0 + $this->wi - $this->wlogo);
192 // Get data
193 $email = '';
194 switch ($this->preferences->pref_card_address) {
195 case 0:
196 $email .= $member->email;
197 break;
198 case 5:
199 $email .= $member->zipcode . ' - ' . $member->town;
200 break;
201 case 6:
202 $email .= $member->nickname;
203 break;
204 case 7:
205 $email .= $member->job;
206 break;
207 case 8:
208 $email .= $member->number;
209 break;
210 }
211
212 // Select strip color according to status
213 switch ($member->status) {
214 case 1:
215 case 2:
216 case 3:
217 case 10:
218 $fcol = $this->bcol;
219 break;
220 case 5:
221 case 6:
222 $fcol = $this->hcol;
223 break;
224 default:
225 $fcol = $this->scol;
226 }
227
228 $nom_adh_ext = '';
229 if ($this->preferences->pref_bool_display_title) {
230 $nom_adh_ext .= $member->stitle;
231 }
232 $nom_adh_ext .= $member->sname;
233 $photo = $member->picture;
234 $photofile = $photo->getPath();
235
236 // Photo 100x130 and logo
237 $this->Image($photofile, $x0, $y0, 25);
238 $this->Image($this->logofile, $xl, $y0, round($this->wlogo));
239
240 // Color=#8C8C8C: Shadow of the year
241 $this->SetTextColor(140);
242 $this->SetFontSize($this->year_font_size);
243
244 $an_cot = $this->an_cot;
245 if ($an_cot === 'DEADLINE') {
246 //get current member deadline
247 $an_cot = $member->due_date;
248 }
249
250 $xan_cot = $x0 + $this->wi - $this->GetStringWidth(
251 $an_cot,
252 self::FONT,
253 'B',
254 $this->year_font_size
255 ) - 0.2;
256 $this->SetXY($xan_cot, $y0 + $this->hlogo - 0.3);
257 $this->writeHTML('<strong>' . $an_cot . '</strong>', false, false);
258
259 // Colored Text (Big label, id, year)
260 $this->SetTextColor($fcol['R'], $fcol['G'], $fcol['B']);
261
262 $this->SetFontSize(8);
263
264 if (!empty($this->preferences->pref_show_id) || !empty($member->number)) {
265 $member_id = (!empty($member->number)) ? $member->number : $member->id;
266 $xid = $x0 + $this->wi - $this->GetStringWidth($member_id, self::FONT, 'B', 8) - 0.2;
267 $this->SetXY($xid, $y0 + 28);
268 $this->writeHTML('<strong>' . $member_id . '</strong>', false, false);
269 }
270 $this->SetFontSize($this->year_font_size);
271 $xan_cot = $xan_cot - 0.3;
272 $this->SetXY($xan_cot, $y0 + $this->hlogo - 0.3);
273 $this->writeHTML('<strong>' . $an_cot . '</strong>', false, false);
274
275 // Abbrev: Adapt font size to text length
276 $this->fixSize(
277 $this->abrev,
278 $this->max_text_size,
279 12,
280 'B'
281 );
282 $this->SetXY($x0 + 27, $y0 + 12);
283 $this->writeHTML('<strong>' . $this->abrev . '</strong>', true, false);
284
285 // Name: Adapt font size to text length
286 $this->SetTextColor(0);
287 $this->fixSize(
288 $nom_adh_ext,
289 $this->max_text_size,
290 8,
291 'B'
292 );
293 $this->SetXY($x0 + 27, $this->getY() + 4);
294 //$this->setX($x0 + 27);
295 $this->writeHTML('<strong>' . $nom_adh_ext . '</strong>', true, false);
296
297 // Email (adapt too)
298 $this->fixSize(
299 $email,
300 $this->max_text_size,
301 6,
302 'B'
303 );
304 $this->setX($x0 + 27);
305 $this->writeHTML('<strong>' . $email . '</strong>', false, false);
306
307 // Lower colored strip with long text
308 $this->SetFillColor($fcol['R'], $fcol['G'], $fcol['B']);
309 $this->SetTextColor(
310 $this->tcol['R'],
311 $this->tcol['G'],
312 $this->tcol['B']
313 );
314 $this->SetFont(self::FONT, 'B', 6);
315 $this->SetXY($x0, $y0 + 33);
316 $this->Cell(
317 $this->wi,
318 7,
319 $this->preferences->pref_card_strip,
320 0,
321 0,
322 'C',
323 true
324 );
325
326 // Draw a gray frame around the card
327 $this->Rect($x0, $y0, $this->wi, $this->he);
328 $nb_card++;
329 }
330 }
331
332 /**
333 * Get card width
334 *
335 * @return integer
336 */
337 public static function getWidth(): int
338 {
339 return defined('GALETTE_CARD_WIDTH') ? GALETTE_CARD_WIDTH : self::WIDTH;
340 }
341
342 /**
343 * Get card height
344 *
345 * @return integer
346 */
347 public static function getHeight(): int
348 {
349 return defined('GALETTE_CARD_HEIGHT') ? GALETTE_CARD_HEIGHT : self::HEIGHT;
350 }
351
352 /**
353 * Get number of columns
354 *
355 * @return integer
356 */
357 public static function getCols(): int
358 {
359 return defined('GALETTE_CARD_COLS') ? GALETTE_CARD_COLS : self::COLS;
360 }
361
362 /**
363 * Get number of rows
364 *
365 * @return integer
366 */
367 public static function getRows(): int
368 {
369 return defined('GALETTE_CARD_ROWS') ? GALETTE_CARD_ROWS : self::ROWS;
370 }
371 }