Passed
Push — master ( eb013e...37f747 )
by Jonathan
04:35
created

Certificate::displayImage()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 41
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 31
nc 4
nop 1
dl 0
loc 41
rs 9.1128
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Certificates
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2009-2016, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
namespace MyArtJaub\Webtrees\Module\Certificates\Model;
14
15
use Fisharebest\Webtrees\Controller\IndividualController;
16
use Fisharebest\Webtrees\Database;
17
use Fisharebest\Webtrees\Date;
18
use Fisharebest\Webtrees\Family;
19
use Fisharebest\Webtrees\Filter;
20
use Fisharebest\Webtrees\I18N;
21
use Fisharebest\Webtrees\Individual;
22
use Fisharebest\Webtrees\Log;
23
use Fisharebest\Webtrees\Media;
24
use Fisharebest\Webtrees\Module;
25
use Fisharebest\Webtrees\Repository;
26
use Fisharebest\Webtrees\Source;
27
use Fisharebest\Webtrees\Tree;
28
use MyArtJaub\Webtrees\Constants;
29
use MyArtJaub\Webtrees\Functions\Functions;
30
use MyArtJaub\Webtrees\Globals;
31
32
/**
33
 * Class for managing certificates, extending a Media object.
34
 * 
35
 */
36
class Certificate extends Media {
37
    
38
    const URL_PREFIX  = 'module.php?mod=myartjaub_certificates&mod_action=Certificate&cid=';
39
		
40
    /** @var string The "TITL" value from the GEDCOM 
41
     * This is a tweak to overcome the private level from the parent object...
42
     */
43
    protected $title = '';
44
    
45
	/**
46
	 * Certificate provider
47
	 * @var CertificateProviderInterface $provider
48
	 */
49
	protected $provider = null;
50
	
51
	/**
52
	 * Certificate type
53
	 * @var string $certType
54
	 */
55
	protected $certType = null;
56
	
57
	/**
58
	 * Certificate date
59
	 * @var (null|Date) $certDate
60
	 */
61
	protected $certDate = null;
62
	
63
	/**
64
	 * Certificate description
65
	 * @var unknown $certDetails
0 ignored issues
show
Bug introduced by
The type MyArtJaub\Webtrees\Modul...tificates\Model\unknown 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...
66
	 */
67
	protected $certDetails = null;
68
	
69
	/**
70
	 * Certificate source
71
	 * @var unknown $source
72
	 */
73
	protected $source = null;
74
	
75
	/**
76
	 * Extends the Media constructor.
77
	 * Create a certificate from the file path
78
	 * @param string $data
79
	 * @param Tree $tree Reference tree
80
	 * @param CertificateProviderInterface $provider
81
	 */
82
	public function __construct($data, Tree $tree, CertificateProviderInterface $provider) {
83
	    $this->provider = $provider;
84
		// Data is only the file name
85
		$data = str_replace("\\", '/', $data);
86
		$xref = Functions::encryptToSafeBase64($data);
87
		$gedcom = sprintf(
88
			'0 @%1$s@ OBJE'.PHP_EOL.
89
			'1 FILE %2$s',
90
			$xref, $data
91
		);
92
		parent::__construct($xref, $gedcom, '', $tree);
93
				
94
		$this->title = basename($this->getFilename(), '.'.$this->extension());
95
		
96
		$match = null;
97
		$ct = preg_match("/(?<year>\d{1,4})(\.(?<month>\d{1,2}))?(\.(?<day>\d{1,2}))?( (?<type>[A-Z]{1,2}) )?(?<details>.*)/", $this->title, $match);
98
		if($ct > 0){
99
			$monthId = (int) $match['month'];
100
			$calendarShortMonths = Functions::getCalendarShortMonths();
101
			$monthShortName = array_key_exists($monthId, $calendarShortMonths) ? $calendarShortMonths[$monthId] : $monthId;
102
			$this->certDate = new Date($match['day'].' '.strtoupper($monthShortName).' '.$match['year']);
103
			$this->certType = $match['type'];
104
			$this->certDetails = $match['details'];			
105
		} else {
106
			$this->certDetails = $this->title;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->title of type string is incompatible with the declared type MyArtJaub\Webtrees\Modul...tificates\Model\unknown of property $certDetails.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
107
		}
108
	}
109
	
110
	/**
111
	 * {@inhericDoc}
112
	 * @see \Fisharebest\Webtrees\GedcomRecord::getInstance()
113
	 */	
114
	static public function getInstance($xref, Tree $tree, $gedcom = null, CertificateProviderInterface $provider = null) {
115
		try{
116
			$certfile = Functions::decryptFromSafeBase64($xref);
117
			
118
			//NEED TO CHECK THAT !!!
119
			if(Functions::isValidPath($certfile, true)) {
120
				return new Certificate($certfile, $tree, $provider);
0 ignored issues
show
Bug introduced by
It seems like $provider can also be of type null; however, parameter $provider of MyArtJaub\Webtrees\Modul...tificate::__construct() does only seem to accept MyArtJaub\Webtrees\Modul...ficateProviderInterface, 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

120
				return new Certificate($certfile, $tree, /** @scrutinizer ignore-type */ $provider);
Loading history...
121
			}
122
		}
123
		catch (\Exception $ex) { 
124
			Log::addErrorLog('Certificate module error : > '.$ex->getMessage().' < with data > '.$xref.' <');
125
		}	
126
127
		return null;
128
	}
129
		
130
	/**
131
	 * {@inhericDoc}
132
	 * @see \Fisharebest\Webtrees\Media::canShowByType()
133
	 */
134
	protected function canShowByType($access_level) {	    
135
		$linked_indis = $this->linkedIndividuals('_ACT');
136
		foreach ($linked_indis as $linked_indi) {
137
			if ($linked_indi && !$linked_indi->canShow($access_level)) {
138
				return false;
139
			}
140
		}
141
		$linked_fams = $this->linkedFamilies('_ACT');
142
		foreach ($linked_fams as $linked_fam) {
143
			if ($linked_fam && !$linked_fam->canShow($access_level)) {
144
				return false;
145
			}
146
		}
147
		
148
		return count($linked_indis) + count($linked_fams) > 0;
149
	}
150
	
151
	/**
152
	 * Define a source associated with the certificate
153
	 *
154
	 * @param string|Source $xref
155
	 */
156
	public function setSource($xref){
157
		if($xref instanceof Source){
158
			$this->source = $xref;
0 ignored issues
show
Documentation Bug introduced by
It seems like $xref of type Fisharebest\Webtrees\Source is incompatible with the declared type MyArtJaub\Webtrees\Modul...tificates\Model\unknown of property $source.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
159
		} else {
160
			$this->source = Source::getInstance($xref, $this->tree);
161
		}
162
	}
163
	
164
	/**
165
	 * {@inheritDoc}
166
	 * @see \Fisharebest\Webtrees\Media::getTitle()
167
	 */
168
	public function getTitle() {
169
	    return $this->title;
170
	}
171
	
172
	/**
173
	 * Returns the certificate date
174
	 *
175
	 * @return Date Certificate date
176
	 */
177
	public function getCertificateDate(){
178
		return $this->certDate;
179
	}
180
	
181
	/**
182
	 * Returns the type of certificate
183
	 *
184
	 * @return string Certificate date
185
	 */
186
	public function getCertificateType(){
187
		return $this->certType;
188
	}
189
	
190
	/**
191
	 * Returns the details of the certificate (basename without the date and type)
192
	 *
193
	 * @return string Certificate details
194
	 */
195
	public function getCertificateDetails(){
196
		return $this->certDetails;
197
	}
198
	
199
	/**
200
	 * Return the city the certificate comes from
201
	 *
202
	 * @return string|NULL Certificate city
203
	 */
204
	public function getCity(){
205
		$chunks = explode('/', $this->getFilename(), 2);
206
		if(count($chunks) > 1) return $chunks[0];
207
		return null;
208
	}
209
	
210
	/**
211
	 * {@inhericDoc}
212
	 * @see \Fisharebest\Webtrees\Media::getServerFilename()
213
	 */
214
	public function getServerFilename($which='main') {
215
		$filename =  $this->provider->getRealCertificatesDirectory() . $this->getFilename();
216
		return Functions::encodeUtf8ToFileSystem($filename);
217
	}
218
	
219
	/**
220
	 * {@inhericDoc}
221
	 * @see \Fisharebest\Webtrees\Media::getHtmlUrlDirect()
222
	 */
223
	public function getHtmlUrlDirect($which = 'main', $download = false) {
224
		$sidstr = ($this->source) ? '&sid='.$this->source->getXref() : '';
225
		return
226
			'module.php?mod='. \MyArtJaub\Webtrees\Constants::MODULE_MAJ_CERTIF_NAME . 
227
			'&mod_action=Certificate@image' . 
228
			'&ged='. $this->tree->getNameUrl() .
229
			'&cid=' . $this->getXref() . $sidstr .
230
			'&cb=' . $this->getEtag($which);
231
	}
232
	
233
	/**
234
	 * Returns the watermark text to be displayed.
235
	 * If a source ID has been provided with the certificate, use this image,
236
	 * otherwise try to find a linked source within the GEDCOM (the first occurence found is used).
237
	 * Else a default text is used.
238
	 *
239
	 * @return string Watermark text
240
	 */
241
	 public function getWatermarkText(){	
242
	 	$module = Module::getModuleByName(Constants::MODULE_MAJ_CERTIF_NAME);
243
	 	
244
	 	if($module) {
245
    		$wmtext = $module->getSetting('MAJ_WM_DEFAULT', I18N::translate('This image is protected under copyright law.'));
246
    		$sid= Filter::get('sid', WT_REGEX_XREF);	
247
    	
248
    		if($sid){
249
    			$this->source = Source::getInstance($sid, $this->tree);
0 ignored issues
show
Documentation Bug introduced by
It seems like Fisharebest\Webtrees\Sou...ance($sid, $this->tree) can also be of type Fisharebest\Webtrees\Family or Fisharebest\Webtrees\GedcomRecord or Fisharebest\Webtrees\Individual or Fisharebest\Webtrees\Media or Fisharebest\Webtrees\Note or Fisharebest\Webtrees\Repository or Fisharebest\Webtrees\Source. However, the property $source is declared as type MyArtJaub\Webtrees\Modul...tificates\Model\unknown. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
250
    		}
251
    		else{
252
    			$this->fetchALinkedSource();  // the method already attach the source to the Certificate object;
253
    		}
254
    		
255
    		if($this->source) {
256
    			$wmtext = '&copy;';
257
    			$repofact = $this->source->getFirstFact('REPO');
258
    			if($repofact) {
259
    				$repo = $repofact->getTarget();
260
    				if($repo && $repo instanceof Repository)  $wmtext .= ' '.$repo->getFullName().' - ';
261
    			}
262
    			$wmtext .= $this->source->getFullName();			
263
    		}	
264
    		return $wmtext;
265
	 	}
266
	 	return '';
267
	}
268
	
269
	/**
270
	 * {@inhericDoc}
271
	 * @see \Fisharebest\Webtrees\Media::displayImage()
272
	 */
273
	public function displayImage($which = 'main') {
274
		$js = '	if(isCertifColorboxActive == 0) { 
275
					activatecertifcolorbox();
276
					isCertifColorboxActive = 1;
277
				}
278
		';
279
		
280
		$script = '';
281
		$controller = Globals::getController();
282
		if($controller && !($controller instanceof IndividualController)){
283
			$controller->addInlineJavascript('$(document).ready(function() { '.$js.' });');
284
		} else {
285
			$script = '<script>' . $js . '</script>';
286
		}
287
		
288
		if ($which == 'icon' || !file_exists($this->getServerFilename())) {
289
			// Use an icon
290
			$image =
291
			'<i dir="auto" class="icon-maj-certificate margin-h-2"' .
292
			' title="' . strip_tags($this->getFullName()) . '"' .
293
			'></i>';
294
		} else {
295
			$imgsize = getimagesize($this->getServerFilename());
296
			$image =
297
			'<img' .
298
			' class ="'. 'certif_image'					 	. '"' .
299
			' dir="'   . 'auto'                           	. '"' . // For the tool-tip
300
			' src="'   . $this->getHtmlUrlDirect() 			. '"' .
301
			' alt="'   . strip_tags($this->getFullName()) 	. '"' .
302
			' title="' . strip_tags($this->getFullName()) 	. '"' .
303
			$imgsize[3] . // height="yyy" width="xxx"
304
			'>';
305
		}	
306
		return
307
		'<a' .
308
		' class="'          . 'certgallery'                          . '"' .
309
		' href="'           . $this->getHtmlUrlDirect()    		 . '"' .
310
		' type="'           . $this->mimeType()                  . '"' .
311
		' data-obje-url="'  . $this->getHtmlUrl()                . '"' .
312
		' data-title="'     . strip_tags($this->getFullName())   . '"' .
313
		'>' . $image . '</a>'.$script;
314
	}
315
	
316
	/**
317
	 * {@inhericDoc}
318
	 * @see \Fisharebest\Webtrees\GedcomRecord::linkedIndividuals()
319
	 */
320
	public function linkedIndividuals($link = '_ACT'){
321
		$rows = Database::prepare(
322
				'SELECT i_id AS xref, i_gedcom AS gedcom'.
323
				' FROM `##individuals`'.
324
				' WHERE i_file= :gedcom_id AND i_gedcom LIKE :gedcom')
325
		->execute(array(
326
		    'gedcom_id' => $this->tree->getTreeId(),
327
		    'gedcom' => '%_ACT '.$this->getFilename().'%'		    
328
		))->fetchAll();
329
		
330
		$list = array();
331
		foreach ($rows as $row) {
332
			$record = Individual::getInstance($row->xref, $this->tree, $row->gedcom);
333
			if ($record->canShowName()) {
334
				$list[] = $record;
335
			}
336
		}
337
		return $list;
338
	}
339
340
	/**
341
	 * {@inhericDoc}
342
	 * @see \Fisharebest\Webtrees\GedcomRecord::linkedFamilies()
343
	 */
344
	public function linkedFamilies($link = '_ACT'){
345
		$rows = Database::prepare(
346
				'SELECT f_id AS xref, f_gedcom AS gedcom'.
347
				' FROM `##families`'.
348
				' WHERE f_file= :gedcom_id AND f_gedcom LIKE :gedcom')
349
		->execute(array(
350
		    'gedcom_id' => $this->tree->getTreeId(),
351
		    'gedcom' => '%_ACT '.$this->getFilename().'%'		    
352
		))->fetchAll();
353
		
354
		$list = array();
355
		foreach ($rows as $row) {
356
			$record = Family::getInstance($row->xref, $this->tree, $row->gedcom);
357
			if ($record->canShowName()) {
358
				$list[] = $record;
359
			}
360
		}
361
		return $list;
362
	}
363
	
364
	/**
365
	 * Returns a unique source linked to the certificate
366
	 *
367
	 * @return Source|NULL Linked source
368
	 */
369
	public function fetchALinkedSource(){		
370
		$sid = null;
371
		
372
		// Try to find in individual, then families, then other types of records. We are interested in the first available value.
373
		$ged =
374
		Database::prepare(
375
				'SELECT i_gedcom AS gedrec FROM `##individuals`'.
376
				' WHERE i_file=:gedcom_id AND i_gedcom LIKE :gedcom')
377
		  ->execute(array(
378
		      'gedcom_id' => $this->tree->getTreeId(), 
379
		      'gedcom' => '%_ACT '.$this->getFilename().'%'		      
380
		  ))->fetchOne();
381
		if(!$ged){
382
			$ged = Database::prepare(
383
					'SELECT f_gedcom AS gedrec FROM `##families`'.
384
					' WHERE f_file=:gedcom_id AND f_gedcom LIKE :gedcom')
385
			     ->execute(array(
386
			         'gedcom_id' => $this->tree->getTreeId(), 
387
			         'gedcom' => '%_ACT '.$this->getFilename().'%'			         
388
			     ))->fetchOne();
389
			if(!$ged){
390
				$ged = Database::prepare(
391
				    'SELECT o_gedcom AS gedrec FROM `##other`'.
392
				    ' WHERE o_file=:gedcom_id AND o_gedcom LIKE :gedcom')
393
				    ->execute(array(
394
				        'gedcom_id' => $this->tree->getTreeId(),
395
				        'gedcom' => '%_ACT '.$this->getFilename().'%'				        
396
				    ))->fetchOne();
397
			}
398
		}
399
		//If a record has been found, parse it to find the source reference.
400
		if($ged){
401
			$gedlines = explode("\n", $ged);
402
			$level = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $level is dead and can be removed.
Loading history...
403
			$levelsource = -1;
404
			$sid_tmp=null;
405
			$sourcefound = false;
406
			foreach($gedlines as $gedline){
407
				// Get the level
408
				$match = null;
409
				if (!$sourcefound && preg_match('~^('.WT_REGEX_INTEGER.') ~', $gedline, $match)) {
410
					$level = $match[1];
411
					//If we are not any more within the context of a source, reset
412
					if($level <= $levelsource){
413
						$levelsource = -1;
414
						$sid_tmp = null;
415
					}
416
					// If a source, get the level and the reference
417
					$match2 = null;
418
					if (preg_match('~^'.$level.' SOUR @('.WT_REGEX_XREF.')@$~', $gedline, $match2)) {
419
						$levelsource = $level;
420
						$sid_tmp=$match2[1];
421
					}
422
					// If the image has be found, get the source reference and exit.
423
					$match3 = null;
424
					if($levelsource>=0 && $sid_tmp && preg_match('~^'.$level.' _ACT '.preg_quote($this->getFilename()).'~', $gedline, $match3)){
425
						$sid = $sid_tmp;
426
						$sourcefound = true;
427
					}
428
				}
429
			}
430
		}
431
		
432
		if($sid) $this->source = Source::getInstance($sid, $this->tree);
0 ignored issues
show
introduced by
$sid is of type mixed, thus it always evaluated to false.
Loading history...
433
		
434
		return $this->source;	
435
	}
436
		
437
}
438
439
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...