Completed
Push — develop ( c314ec...310a97 )
by Greg
13:42
created

ClippingsCartModule::getMenu()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 17
rs 8.8571
cc 5
eloc 11
nc 8
nop 0
1
<?php
2
/**
3
 * webtrees: online genealogy
4
 * Copyright (C) 2015 webtrees development team
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 * GNU General Public License for more details.
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15
 */
16
namespace Fisharebest\Webtrees\Module;
17
18
use Fisharebest\Webtrees\Auth;
19
use Fisharebest\Webtrees\Controller\PageController;
20
use Fisharebest\Webtrees\Family;
21
use Fisharebest\Webtrees\Filter;
22
use Fisharebest\Webtrees\Functions\FunctionsPrint;
23
use Fisharebest\Webtrees\GedcomRecord;
24
use Fisharebest\Webtrees\I18N;
25
use Fisharebest\Webtrees\Individual;
26
use Fisharebest\Webtrees\Menu;
27
use Fisharebest\Webtrees\Module\ClippingsCart\ClippingsCartController;
28
use Fisharebest\Webtrees\Session;
29
30
/**
31
 * Class ClippingsCartModule
32
 */
33
class ClippingsCartModule extends AbstractModule implements ModuleMenuInterface, ModuleSidebarInterface {
34
	/** {@inheritdoc} */
35
	public function getTitle() {
36
		return /* I18N: Name of a module */ I18N::translate('Clippings cart');
37
	}
38
39
	/** {@inheritdoc} */
40
	public function getDescription() {
41
		return /* I18N: Description of the “Clippings cart” module */ I18N::translate('Select records from your family tree and save them as a GEDCOM file.');
42
	}
43
44
	/**
45
	 * What is the default access level for this module?
46
	 *
47
	 * Some modules are aimed at admins or managers, and are not generally shown to users.
48
	 *
49
	 * @return int
50
	 */
51
	public function defaultAccessLevel() {
52
		return Auth::PRIV_USER;
53
	}
54
55
	/**
56
	 * This is a general purpose hook, allowing modules to respond to routes
57
	 * of the form module.php?mod=FOO&mod_action=BAR
58
	 *
59
	 * @param string $mod_action
60
	 */
61
	public function modAction($mod_action) {
62
		switch ($mod_action) {
63
		case 'ajax':
64
			$html = $this->getSidebarAjaxContent();
65
			header('Content-Type: text/html; charset=UTF-8');
66
			echo $html;
67
			break;
68
		case 'index':
69
			global $controller, $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
70
71
			$MAX_PEDIGREE_GENERATIONS = $WT_TREE->getPreference('MAX_PEDIGREE_GENERATIONS');
72
73
			$clip_ctrl = new ClippingsCartController;
74
			$cart      = Session::get('cart');
75
76
			$controller = new PageController;
77
			$controller
78
				->setPageTitle($this->getTitle())
79
				->PageHeader()
80
				->addExternalJavascript(WT_AUTOCOMPLETE_JS_URL)
81
				->addInlineJavascript('autocomplete();');
82
83
			echo '<script>';
84
			echo 'function radAncestors(elementid) {var radFamilies=document.getElementById(elementid);radFamilies.checked=true;}';
85
			echo '</script>';
86
87
			if (!$cart[$WT_TREE->getTreeId()]) {
88
				echo '<h2>', I18N::translate('Family tree clippings cart'), '</h2>';
89
			}
90
91
			if ($clip_ctrl->action == 'add') {
92
				$record = GedcomRecord::getInstance($clip_ctrl->id, $WT_TREE);
93
				if ($clip_ctrl->type === 'FAM') { ?>
94
				<form action="module.php" method="get">
95
					<input type="hidden" name="mod" value="clippings">
96
					<input type="hidden" name="mod_action" value="index">
97
					<input type="hidden" name="id" value="<?php echo $clip_ctrl->id; ?>">
98
					<input type="hidden" name="type" value="<?php echo $clip_ctrl->type; ?>">
99
					<input type="hidden" name="action" value="add1">
100
					<table>
101
						<thead>
102
							<tr>
103
								<td class="topbottombar">
104
									<?php echo I18N::translate('Add to the clippings cart'); ?>
105
								</td>
106
							</tr>
107
						</thead>
108
						<tbody>
109
							<tr>
110
								<td class="optionbox">
111
									<input type="radio" name="others" value="parents">
112
									<?php echo $record->getFullName(); ?>
113
								</td>
114
							</tr>
115
							<tr>
116
								<td class="optionbox">
117
									<input type="radio" name="others" value="members" checked>
118
									<?php echo /* I18N: %s is a family (husband + wife) */ I18N::translate('%s and their children', $record->getFullName()); ?>
119
								</td>
120
							</tr>
121
							<tr>
122
								<td class="optionbox">
123
									<input type="radio" name="others" value="descendants">
124
									<?php echo /* I18N: %s is a family (husband + wife) */ I18N::translate('%s and their descendants', $record->getFullName()); ?>
125
								</td>
126
							</tr>
127
						</tbody>
128
						<tfoot>
129
							<tr>
130
								<td class="topbottombar"><input type="submit" value="<?php echo I18N::translate('continue'); ?>">
131
								</td>
132
							</tr>
133
						</tfoot>
134
					</table>
135
				</form>
136
				<?php } elseif ($clip_ctrl->type === 'INDI') { ?>
137
				<form action="module.php" method="get">
138
					<input type="hidden" name="mod" value="clippings">
139
					<input type="hidden" name="mod_action" value="index">
140
					<input type="hidden" name="id" value="<?php echo $clip_ctrl->id; ?>">
141
					<input type="hidden" name="type" value="<?php echo $clip_ctrl->type; ?>">
142
					<input type="hidden" name="action" value="add1"></td></tr>
143
					<table>
144
						<thead>
145
							<tr>
146
								<td class="topbottombar">
147
									<?php echo I18N::translate('Add to the clippings cart'); ?>
148
								</td>
149
							</tr>
150
						</thead>
151
						<tbody>
152
							<tr>
153
								<td class="optionbox">
154
									<label>
155
										<input type="radio" name="others" checked value="none">
156
										<?php echo $record->getFullName(); ?>
157
									</label>
158
								</td>
159
							</tr>
160
							<tr>
161
								<td class="optionbox">
162
									<label>
163
										<input type="radio" name="others" value="parents">
164
										<?php
165 View Code Duplication
										if ($record->getSex() === 'F') {
166
											echo /* I18N: %s is a woman's name */ I18N::translate('%s, her parents and siblings', $record->getFullName());
167
										} else {
168
											echo /* I18N: %s is a man's name */ I18N::translate('%s, his parents and siblings', $record->getFullName());
169
										}
170
										?>
171
									</label>
172
								</td>
173
							</tr>
174
							<tr>
175
								<td class="optionbox">
176
									<label>
177
										<input type="radio" name="others" value="members">
178
										<?php
179 View Code Duplication
										if ($record->getSex() === 'F') {
180
											echo /* I18N: %s is a woman's name */ I18N::translate('%s, her spouses and children', $record->getFullName());
181
										} else {
182
											echo /* I18N: %s is a man's name */ I18N::translate('%s, his spouses and children', $record->getFullName());
183
										}
184
										?>
185
									</label>
186
								</td>
187
							</tr>
188
							<tr>
189
								<td class="optionbox">
190
									<label>
191
										<input type="radio" name="others" value="ancestors" id="ancestors">
192
										<?php
193 View Code Duplication
										if ($record->getSex() === 'F') {
194
										echo /* I18N: %s is a woman's name */ I18N::translate('%s and her ancestors', $record->getFullName());
195
										} else {
196
										echo /* I18N: %s is a man's name */ I18N::translate('%s and his ancestors', $record->getFullName());
197
										}
198
									?>
199
									</label>
200
									<br>
201
									<?php echo I18N::translate('Number of generations'); ?>
202
									<input type="text" size="5" name="level1" value="<?php echo $MAX_PEDIGREE_GENERATIONS; ?>" onfocus="radAncestors('ancestors');">
203
								</td>
204
							</tr>
205
							<tr>
206
								<td class="optionbox">
207
									<label>
208
										<input type="radio" name="others" value="ancestorsfamilies" id="ancestorsfamilies">
209
										<?php
210 View Code Duplication
										if ($record->getSex() === 'F') {
211
											echo /* I18N: %s is a woman's name */ I18N::translate('%s, her ancestors and their families', $record->getFullName());
212
										} else {
213
											echo /* I18N: %s is a man's name */ I18N::translate('%s, his ancestors and their families', $record->getFullName());
214
										}
215
										?>
216
									</label>
217
									<br >
218
									<?php echo I18N::translate('Number of generations'); ?>
219
									<input type="text" size="5" name="level2" value="<?php echo $MAX_PEDIGREE_GENERATIONS; ?>" onfocus="radAncestors('ancestorsfamilies');">
220
								</td>
221
							</tr>
222
							<tr>
223
								<td class="optionbox">
224
									<label>
225
										<input type="radio" name="others" value="descendants" id="descendants">
226
										<?php
227 View Code Duplication
										if ($record->getSex() === 'F') {
228
											echo /* I18N: %s is a woman's name */ I18N::translate('%s, her spouses and descendants', $record->getFullName());
229
										} else {
230
											echo /* I18N: %s is a man's name */ I18N::translate('%s, his spouses and descendants', $record->getFullName());
231
										}
232
										?>
233
									</label>
234
									<br >
235
									<?php echo I18N::translate('Number of generations'); ?>
236
									<input type="text" size="5" name="level3" value="<?php echo $MAX_PEDIGREE_GENERATIONS; ?>" onfocus="radAncestors('descendants');">
237
								</td>
238
							</tr>
239
						</tbody>
240
						<tfoot>
241
							<tr>
242
								<td class="topbottombar">
243
									<input type="submit" value="<?php echo I18N::translate('continue'); ?>">
244
								</td>
245
							</tr>
246
						</tfoot>
247
					</table>
248
				</form>
249
				<?php } elseif ($clip_ctrl->type === 'SOUR') { ?>
250
				<form action="module.php" method="get">
251
					<input type="hidden" name="mod" value="clippings">
252
					<input type="hidden" name="mod_action" value="index">
253
					<input type="hidden" name="id" value="<?php echo $clip_ctrl->id; ?>">
254
					<input type="hidden" name="type" value="<?php echo $clip_ctrl->type; ?>">
255
					<input type="hidden" name="action" value="add1"></td></tr>
256
					<table>
257
						<thead>
258
							<tr>
259
								<td class="topbottombar">
260
									<?php echo I18N::translate('Add to the clippings cart'); ?>
261
								</td>
262
							</tr>
263
						</thead>
264
						<tbody>
265
							<tr>
266
								<td class="optionbox">
267
									<label>
268
										<input type="radio" name="others" checked value="none">
269
										<?php echo $record->getFullName(); ?>
270
									</label>
271
								</td>
272
							</tr>
273
							<tr>
274
								<td class="optionbox">
275
									<label>
276
										<input type="radio" name="others" value="linked">
277
										<?php echo /* I18N: %s is the name of a source */ I18N::translate('%s and the individuals that reference it.', $record->getFullName()); ?>
278
									</label>
279
								</td>
280
							</tr>
281
						</tbody>
282
						<tfoot>
283
							<tr>
284
								<td class="topbottombar">
285
									<input type="submit" value="<?php echo I18N::translate('continue'); ?>">
286
								</td>
287
							</tr>
288
						</tfoot>
289
					</table>
290
				</form>
291
				<?php }
292
				}
293
294
			if (!$cart[$WT_TREE->getTreeId()]) {
295
				if ($clip_ctrl->action != 'add') {
296
					echo I18N::translate('The clippings cart allows you to take extracts (“clippings”) from this family tree and bundle them up into a single file for downloading and subsequent importing into your own genealogy program. The downloadable file is recorded in GEDCOM format.<br><ul><li>How to take clippings?<br>This is really simple. Whenever you see a clickable name (individual, family, or source) you can go to the Details page of that name. There you will see the <b>Add to clippings cart</b> option. When you click that link you will be offered several options to download.</li><li>How to download?<br>Once you have items in your cart, you can download them just by clicking the “Download” link. Follow the instructions and links.</li></ul>');
297
					?>
298
					<form method="get" name="addin" action="module.php">
299
					<input type="hidden" name="mod" value="clippings">
300
					<input type="hidden" name="mod_action" value="index">
301
						<table>
302
							<thead>
303
								<tr>
304
									<td colspan="2" class="topbottombar">
305
										<?php echo I18N::translate('Add to the clippings cart'); ?>
306
									</td>
307
								</tr>
308
							</thead>
309
							<tbody>
310
								<tr>
311
									<td class="optionbox">
312
										<input type="hidden" name="action" value="add">
313
										<input type="text" data-autocomplete-type="IFSRO" name="id" id="cart_item_id" size="5">
314
									</td>
315
									<td class="optionbox">
316
										<?php echo FunctionsPrint::printFindIndividualLink('cart_item_id'); ?>
317
										<?php echo FunctionsPrint::printFindFamilyLink('cart_item_id'); ?>
318
										<?php echo FunctionsPrint::printFindSourceLink('cart_item_id', ''); ?>
319
										<input type="submit" value="<?php echo I18N::translate('Add'); ?>">
320
									</td>
321
								</tr>
322
							</tbody>
323
						</table>
324
					</form>
325
					<?php
326
				}
327
328
				// -- end new lines
329
				echo I18N::translate('Your clippings cart is empty.');
330
			} else {
331
				// Keep track of the INDI from the parent page, otherwise it will
332
				// get lost after ajax updates
333
				$pid = Filter::get('pid', WT_REGEX_XREF);
334
335
				if ($clip_ctrl->action != 'download' && $clip_ctrl->action != 'add') { ?>
336
					<table><tr><td class="width33" valign="top" rowspan="3">
337
					<form method="get" action="module.php">
338
					<input type="hidden" name="mod" value="clippings">
339
					<input type="hidden" name="mod_action" value="index">
340
					<input type="hidden" name="action" value="download">
341
					<input type="hidden" name="pid" value="<?php echo $pid; ?>">
342
					<table>
343
					<tr><td colspan="2" class="topbottombar"><h2><?php echo I18N::translate('Download'); ?></h2></td></tr>
344
					<tr>
345
						<td class="descriptionbox width50 wrap">
346
							<?php echo I18N::translate('To reduce the size of the download, you can compress the data into a .ZIP file. You will need to uncompress the .ZIP file before you can use it.'); ?>
347
						</td>
348
						<td class="optionbox wrap">
349
							<input type="checkbox" name="Zip" value="yes">
350
							<?php echo I18N::translate('Zip file(s)'); ?>
351
						</td>
352
					</tr>
353
					<tr>
354
						<td class="descriptionbox width50 wrap">
355
							<?php echo I18N::translate('Include media (automatically zips files)'); ?>
356
						</td>
357
					<td class="optionbox"><input type="checkbox" name="IncludeMedia" value="yes"></td></tr>
358
359
					<?php if (Auth::isManager($WT_TREE)) { ?>
360
						<tr><td class="descriptionbox width50 wrap"><?php echo I18N::translate('Apply privacy settings'); ?></td>
361
						<td class="optionbox">
362
							<input type="radio" name="privatize_export" value="none" checked> <?php echo I18N::translate('None'); ?><br>
363
							<input type="radio" name="privatize_export" value="gedadmin"> <?php echo I18N::translate('Manager'); ?><br>
364
							<input type="radio" name="privatize_export" value="user"> <?php echo I18N::translate('Member'); ?><br>
365
							<input type="radio" name="privatize_export" value="visitor"> <?php echo I18N::translate('Visitor'); ?>
366
						</td></tr>
367
					<?php } elseif (Auth::isMember($WT_TREE)) { ?>
368
						<tr><td class="descriptionbox width50 wrap"><?php echo I18N::translate('Apply privacy settings'); ?></td>
369
						<td class="optionbox">
370
							<input type="radio" name="privatize_export" value="user" checked> <?php echo I18N::translate('Member'); ?><br>
371
							<input type="radio" name="privatize_export" value="visitor"> <?php echo I18N::translate('Visitor'); ?>
372
						</td></tr>
373
					<?php } ?>
374
375
					<tr><td class="descriptionbox width50 wrap"><?php echo I18N::translate('Convert from UTF-8 to ISO-8859-1'); ?></td>
376
					<td class="optionbox"><input type="checkbox" name="convert" value="yes"></td></tr>
377
378
					<tr><td class="descriptionbox width50 wrap"><?php echo I18N::translate('Add the GEDCOM media path to filenames'); ?></td>
379
					<td class="optionbox">
380
						<input type="checkbox" name="conv_path" value="<?php echo Filter::escapeHtml($WT_TREE->getPreference('GEDCOM_MEDIA_PATH')); ?>">
381
						<span dir="auto"><?php echo Filter::escapeHtml($WT_TREE->getPreference('GEDCOM_MEDIA_PATH')); ?></span>
382
					</td></tr>
383
384
					<tr><td class="topbottombar" colspan="2">
385
					<input type="submit" value="<?php echo I18N::translate('Download'); ?>">
386
					</form>
387
					</td></tr>
388
					</table>
389
					</td></tr>
390
					</table>
391
					<br>
392
393
					<form method="get" name="addin" action="module.php">
394
						<input type="hidden" name="mod" value="clippings">
395
						<input type="hidden" name="mod_action" value="index">
396
						<table>
397
							<thead>
398
								<tr>
399
									<td colspan="2" class="topbottombar" style="text-align:center; ">
400
										<?php echo I18N::translate('Add to the clippings cart'); ?>
401
									</td>
402
								</tr>
403
							</thead>
404
							<tbody>
405
								<tr>
406
									<td class="optionbox">
407
										<input type="hidden" name="action" value="add">
408
										<input type="text" data-autocomplete-type="IFSRO" name="id" id="cart_item_id" size="8">
409
									</td>
410
									<td class="optionbox">
411
										<?php echo FunctionsPrint::printFindIndividualLink('cart_item_id'); ?>
412
										<?php echo FunctionsPrint::printFindFamilyLink('cart_item_id'); ?>
413
										<?php echo FunctionsPrint::printFindSourceLink('cart_item_id'); ?>
414
										<input type="submit" value="<?php echo I18N::translate('Add'); ?>">
415
									</td>
416
								</tr>
417
								</tbody>
418
						</table>
419
					</form>
420
421
422
				<?php } ?>
423
				<br><a href="module.php?mod=clippings&amp;mod_action=index&amp;action=empty"><?php echo I18N::translate('Empty the clippings cart'); ?></a>
424
				</td></tr>
425
426
				<tr><td class="topbottombar"><h2><?php echo I18N::translate('Family tree clippings cart'); ?></h2></td></tr>
427
428
				<tr><td valign="top">
429
				<table id="mycart" class="sortable list_table width100">
430
					<tr>
431
						<th class="list_label"><?php echo I18N::translate('Record'); ?></th>
432
						<th class="list_label"><?php echo I18N::translate('Remove'); ?></th>
433
					</tr>
434
			<?php
435
				foreach (array_keys($cart[$WT_TREE->getTreeId()]) as $xref) {
436
					$record = GedcomRecord::getInstance($xref, $WT_TREE);
437
					if ($record) {
438
						switch ($record::RECORD_TYPE) {
439
						case 'INDI': $icon = 'icon-indis'; break;
440
						case 'FAM':  $icon = 'icon-sfamily'; break;
441
						case 'SOUR': $icon = 'icon-source'; break;
442
						case 'REPO': $icon = 'icon-repository'; break;
443
						case 'NOTE': $icon = 'icon-note'; break;
444
						case 'OBJE': $icon = 'icon-media'; break;
445
						default:     $icon = 'icon-clippings'; break;
446
						}
447
						?>
448
						<tr><td class="list_value">
449
							<i class="<?php echo $icon; ?>"></i>
450
						<?php
451
						echo '<a href="', $record->getHtmlUrl(), '">', $record->getFullName(), '</a>';
452
						?>
453
						</td>
454
						<td class="list_value center vmiddle"><a href="module.php?mod=clippings&amp;mod_action=index&amp;action=remove&amp;id=<?php echo $xref; ?>" class="icon-remove" title="<?php echo I18N::translate('Remove'); ?>"></a></td>
455
					</tr>
456
					<?php
457
					}
458
				}
459
			?>
460
				</table>
461
				</td></tr></table>
462
			<?php
463
			}
464
			break;
465
		default:
466
			http_response_code(404);
467
			break;
468
		}
469
	}
470
471
	/**
472
	 * The user can re-order menus. Until they do, they are shown in this order.
473
	 *
474
	 * @return int
475
	 */
476
	public function defaultMenuOrder() {
477
		return 20;
478
	}
479
480
	/**
481
	 * A menu, to be added to the main application menu.
482
	 *
483
	 * @return Menu|null
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Menu.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
484
	 */
485
	public function getMenu() {
486
		global $controller, $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
487
488
		$submenus = array();
489
		if (isset($controller->record)) {
490
			$submenus[] = new Menu($this->getTitle(), 'module.php?mod=clippings&amp;mod_action=index&amp;ged=' . $WT_TREE->getNameUrl(), 'menu-clippingscart', array('rel' => 'nofollow'));
491
		}
492
		if (!empty($controller->record) && $controller->record->canShow()) {
493
			$submenus[] = new Menu(I18N::translate('Add to the clippings cart'), 'module.php?mod=clippings&amp;mod_action=index&amp;action=add&amp;id=' . $controller->record->getXref(), 'menu-clippingsadd', array('rel' => 'nofollow'));
494
		}
495
496
		if ($submenus) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $submenus of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
497
			return new Menu($this->getTitle(), '#', 'menu-clippings', array('rel' => 'nofollow'), $submenus);
498
		} else {
499
			return new Menu($this->getTitle(), 'module.php?mod=clippings&amp;mod_action=index&amp;ged=' . $WT_TREE->getNameUrl(), 'menu-clippings', array('rel' => 'nofollow'));
500
		}
501
	}
502
503
	/** {@inheritdoc} */
504
	public function defaultSidebarOrder() {
505
		return 60;
506
	}
507
508
	/** {@inheritdoc} */
509
	public function hasSidebarContent() {
510
		// Creating a controller has the side effect of initialising the cart
511
		new ClippingsCartController;
512
513
		return true;
514
	}
515
516
	/**
517
	 * Load this sidebar synchronously.
518
	 *
519
	 * @return string
520
	 */
521
	public function getSidebarContent() {
522
		global $controller;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
523
524
		$controller->addInlineJavascript('
525
				jQuery("#sb_clippings_content").on("click", ".add_cart, .remove_cart", function() {
526
					jQuery("#sb_clippings_content").load(this.href);
527
					return false;
528
				});
529
			');
530
531
		return '<div id="sb_clippings_content">' . $this->getCartList() . '</div>';
532
	}
533
534
	/** {@inheritdoc} */
535
	public function getSidebarAjaxContent() {
0 ignored issues
show
Coding Style introduced by
getSidebarAjaxContent uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
536
		global $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
537
538
		$cart = Session::get('cart');
539
540
		$clip_ctrl         = new ClippingsCartController;
541
		$add               = Filter::get('add', WT_REGEX_XREF);
542
		$add1              = Filter::get('add1', WT_REGEX_XREF);
543
		$remove            = Filter::get('remove', WT_REGEX_XREF);
544
		$others            = Filter::get('others');
545
		$clip_ctrl->level1 = Filter::getInteger('level1');
546
		$clip_ctrl->level2 = Filter::getInteger('level2');
547
		$clip_ctrl->level3 = Filter::getInteger('level3');
548
		if ($add) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $add of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
549
			$record = GedcomRecord::getInstance($add, $WT_TREE);
550
			if ($record) {
551
				$clip_ctrl->id   = $record->getXref();
552
				$clip_ctrl->type = $record::RECORD_TYPE;
553
				$clip_ctrl->addClipping($record);
554
			}
555
		} elseif ($add1) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $add1 of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
556
			$record = Individual::getInstance($add1, $WT_TREE);
557
			if ($record) {
558
				$clip_ctrl->id   = $record->getXref();
559
				$clip_ctrl->type = $record::RECORD_TYPE;
560
				if ($others == 'parents') {
561
					foreach ($record->getChildFamilies() as $family) {
562
						$clip_ctrl->addClipping($family);
563
						$clip_ctrl->addFamilyMembers($family);
564
					}
565
				} elseif ($others == 'ancestors') {
566
					$clip_ctrl->addAncestorsToCart($record, $clip_ctrl->level1);
0 ignored issues
show
Documentation introduced by
$record is of type object<Fisharebest\Webtrees\GedcomRecord>, but the function expects a null|object<Fisharebest\Webtrees\Individual>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
567
				} elseif ($others == 'ancestorsfamilies') {
568
					$clip_ctrl->addAncestorsToCartFamilies($record, $clip_ctrl->level2);
0 ignored issues
show
Documentation introduced by
$record is of type object<Fisharebest\Webtrees\GedcomRecord>, but the function expects a null|object<Fisharebest\Webtrees\Individual>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
569
				} elseif ($others == 'members') {
570
					foreach ($record->getSpouseFamilies() as $family) {
571
						$clip_ctrl->addClipping($family);
572
						$clip_ctrl->addFamilyMembers($family);
573
					}
574
				} elseif ($others == 'descendants') {
575
					foreach ($record->getSpouseFamilies() as $family) {
576
						$clip_ctrl->addClipping($family);
577
						$clip_ctrl->addFamilyDescendancy($family, $clip_ctrl->level3);
578
					}
579
				}
580
			}
581
		} elseif ($remove) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $remove of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
582
			unset($cart[$WT_TREE->getTreeId()][$remove]);
583
			Session::put('cart', $cart);
584
		} elseif (isset($_REQUEST['empty'])) {
585
			$cart[$WT_TREE->getTreeId()] = array();
586
			Session::put('cart', $cart);
587
		} elseif (isset($_REQUEST['download'])) {
588
			return $this->downloadForm($clip_ctrl);
589
		}
590
591
		return $this->getCartList();
592
	}
593
594
	/**
595
	 * A list for the side bar.
596
	 *
597
	 * @return string
598
	 */
599
	public function getCartList() {
600
		global $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
601
602
		$cart = Session::get('cart', array());
603
		if (!array_key_exists($WT_TREE->getTreeId(), $cart)) {
604
			$cart[$WT_TREE->getTreeId()] = array();
605
		}
606
		$pid = Filter::get('pid', WT_REGEX_XREF);
607
608
		if (!$cart[$WT_TREE->getTreeId()]) {
609
			$out = I18N::translate('Your clippings cart is empty.');
610
		} else {
611
			$out = '<ul>';
612
			foreach (array_keys($cart[$WT_TREE->getTreeId()]) as $xref) {
613
				$record = GedcomRecord::getInstance($xref, $WT_TREE);
614
				if ($record instanceof Individual || $record instanceof Family) {
615
					switch ($record::RECORD_TYPE) {
616
					case 'INDI':
617
						$icon = 'icon-indis';
618
						break;
619
					case 'FAM':
620
						$icon = 'icon-sfamily';
621
						break;
622
					}
623
					$out .= '<li>';
624
					if (!empty($icon)) {
625
						$out .= '<i class="' . $icon . '"></i>';
626
					}
627
					$out .= '<a href="' . $record->getHtmlUrl() . '">';
628
					if ($record instanceof Individual) {
629
						$out .= $record->getSexImage();
630
					}
631
					$out .= ' ' . $record->getFullName() . ' ';
632
					if ($record instanceof Individual && $record->canShow()) {
633
						$out .= ' (' . $record->getLifeSpan() . ')';
634
					}
635
					$out .= '</a>';
636
					$out .= '<a class="icon-remove remove_cart" href="module.php?mod=' . $this->getName() . '&amp;mod_action=ajax&amp;sb_action=clippings&amp;remove=' . $xref . '&amp;pid=' . $pid . '" title="' . I18N::translate('Remove') . '"></a>';
637
					$out .= '</li>';
638
				}
639
			}
640
			$out .= '</ul>';
641
		}
642
643
		if ($cart[$WT_TREE->getTreeId()]) {
644
			$out .=
645
				'<br><a href="module.php?mod=' . $this->getName() . '&amp;mod_action=ajax&amp;sb_action=clippings&amp;empty=true&amp;pid=' . $pid . '" class="remove_cart">' .
646
				I18N::translate('Empty the clippings cart') .
647
				'</a>' .
648
				'<br>' .
649
				'<a href="module.php?mod=' . $this->getName() . '&amp;mod_action=ajax&amp;sb_action=clippings&amp;download=true&amp;pid=' . $pid . '" class="add_cart">' .
650
				I18N::translate('Download') .
651
				'</a>';
652
		}
653
		$record = Individual::getInstance($pid, $WT_TREE);
654
		if ($record && !array_key_exists($record->getXref(), $cart[$WT_TREE->getTreeId()])) {
655
			$out .= '<br><a href="module.php?mod=' . $this->getName() . '&amp;mod_action=ajax&amp;sb_action=clippings&amp;add=' . $pid . '&amp;pid=' . $pid . '" class="add_cart"><i class="icon-clippings"></i> ' . I18N::translate('Add %s to the clippings cart', $record->getFullName()) . '</a>';
656
		}
657
658
		return $out;
659
	}
660
661
	/**
662
	 * A form to choose the download options.
663
	 *
664
	 * @param ClippingsCartController $clip_ctrl
665
	 *
666
	 * @return string
667
	 */
668
	public function downloadForm(ClippingsCartController $clip_ctrl) {
669
		global $WT_TREE;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
670
671
		$pid = Filter::get('pid', WT_REGEX_XREF);
672
673
		$out = '<script>';
674
		$out .= 'function cancelDownload() {
675
				var link = "module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=clippings&pid=' . $pid . '";
676
				jQuery("#sb_clippings_content").load(link);
677
			}';
678
		$out .= '</script>';
679
		$out .= '<form method="get" action="module.php">
680
		<input type="hidden" name="mod" value="clippings">
681
		<input type="hidden" name="mod_action" value="index">
682
		<input type="hidden" name="pid" value="' . $pid . '">
683
		<input type="hidden" name="action" value="download">
684
		<table>
685
		<tr><td colspan="2" class="topbottombar"><h2>' . I18N::translate('Download') . '</h2></td></tr>
686
		<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Zip file(s)') . '</td>
687
		<td class="optionbox"><input type="checkbox" name="Zip" value="yes" checked></td></tr>
688
689
		<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Include media (automatically zips files)') . '</td>
690
		<td class="optionbox"><input type="checkbox" name="IncludeMedia" value="yes" checked></td></tr>
691
		';
692
693
		if (Auth::isManager($WT_TREE)) {
694
			$out .=
695
				'<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Apply privacy settings') . '</td>' .
696
				'<td class="optionbox">' .
697
				'<input type="radio" name="privatize_export" value="none" checked> ' . I18N::translate('None') . '<br>' .
698
				'<input type="radio" name="privatize_export" value="gedadmin"> ' . I18N::translate('Manager') . '<br>' .
699
				'<input type="radio" name="privatize_export" value="user"> ' . I18N::translate('Member') . '<br>' .
700
				'<input type="radio" name="privatize_export" value="visitor"> ' . I18N::translate('Visitor') .
701
				'</td></tr>';
702 View Code Duplication
		} elseif (Auth::isMember($WT_TREE)) {
703
			$out .=
704
				'<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Apply privacy settings') . '</td>' .
705
				'<td class="list_value">' .
706
				'<input type="radio" name="privatize_export" value="user" checked> ' . I18N::translate('Member') . '<br>' .
707
				'<input type="radio" name="privatize_export" value="visitor"> ' . I18N::translate('Visitor') .
708
				'</td></tr>';
709
		}
710
711
		$out .= '
712
		<tr><td class="descriptionbox width50 wrap">' . I18N::translate('Convert from UTF-8 to ISO-8859-1') . '</td>
713
		<td class="optionbox"><input type="checkbox" name="convert" value="yes"></td></tr>
714
715
		<tr>
716
		<td class="descriptionbox width50 wrap">' . I18N::translate('Add the GEDCOM media path to filenames') . '</td>
717
		<td class="optionbox">
718
		<input type="checkbox" name="conv_path" value="' . Filter::escapeHtml($WT_TREE->getPreference('GEDCOM_MEDIA_PATH')) . '">
719
		<span dir="auto">' . Filter::escapeHtml($WT_TREE->getPreference('GEDCOM_MEDIA_PATH')) . '</span></td>
720
		</tr>
721
722
		<input type="hidden" name="conv_path" value="' . $clip_ctrl->conv_path . '">
723
724
		</td></tr>
725
726
		<tr><td class="topbottombar" colspan="2">
727
		<input type="button" value="' . I18N::translate('Cancel') . '" onclick="cancelDownload();">
728
		<input type="submit" value="' . I18N::translate('Download') . '">
729
		</form>';
730
731
		return $out;
732
	}
733
}
734