Test Setup Failed
Branch botk5 (3fe4ef)
by Enrico
02:33
created

LocalBusiness   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 217
Duplicated Lines 7.83 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 56
lcom 1
cbo 2
dl 17
loc 217
rs 6.5957
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B buildNormalizedAddress() 0 17 8
F asTurtle() 17 92 47

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like LocalBusiness often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use LocalBusiness, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace BOTK\Model;
3
4
use BOTK\Exceptions\DataModelException;
5
use BOTK\ModelInterface;
6
7
/**
8
 * An ibrid class that merge the semantic of schema:organization, schema:place and schema:geo, 
9
 * it is similar to schema:LocalBusiness.
10
 * Allows the bulk setup of properties
11
 */
12
class LocalBusiness extends AbstractModel implements ModelInterface 
13
{
14
	protected static $DEFAULT_OPTIONS = array (
15
		'businessType'		=> array(		
16
								// additional types  as extension of schema:LocalBusiness
17
								'filter'    => FILTER_DEFAULT,
18
                            	'flags'  	=> FILTER_FORCE_ARRAY,
19
			                   ),
20
		'taxID'				=> array(	
21
								'filter'    => FILTER_CALLBACK,
22
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_TOKEN',
23
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
24
			                   ),
25
		'vatID'				=> array(	// italian rules
26
								'filter'    => FILTER_VALIDATE_REGEXP,
27
		                        'options' 	=> array('regexp'=>'/^[0-9]{11}$/'),
28
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
29
			                   ),
30
		'legalName'			=> array(
31
								'filter'    => FILTER_CALLBACK,
32
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_ADDRESS',
33
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
34
			                   ),
35
		'businessName'		=> array(
36
								// a schema:alternateName for schema:PostalAddress
37
								'filter'    => FILTER_DEFAULT,
38
                            	'flags'  	=> FILTER_FORCE_ARRAY,
39
							   ),
40
		'addressCountry'	=> array(
41
								'default'	=> 'IT',		
42
								'filter'    => FILTER_VALIDATE_REGEXP,
43
		                        'options' 	=> array('regexp'=>'/^[A-Z]{2}$/'),
44
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
45
			                   ),
46
		'addressLocality'	=> array(	
47
								'filter'    => FILTER_CALLBACK,
48
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_ADDRESS',
49
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
50
			                   ),
51
		'addressRegion'		=> array(	
52
								'filter'    => FILTER_CALLBACK,
53
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_ADDRESS',
54
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
55
			                   ),
56
		'streetAddress'		=> array(	
57
								'filter'    => FILTER_CALLBACK,
58
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_ADDRESS',
59
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
60
			                   ),
61
		'postalCode'		=> array(	// italian rules
62
								'filter'    => FILTER_VALIDATE_REGEXP,
63
		                        'options' 	=> array('regexp'=>'/^[0-9]{5}$/'),
64
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
65
			                   ),
66
		'page'				=> array(	
67
								'filter'    => FILTER_SANITIZE_URL,
68
                            	'flags'  	=> FILTER_FORCE_ARRAY,
69
			                   ),
70
		'telephone'			=> array(	
71
								'filter'    => FILTER_CALLBACK,	
72
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_TELEPHONE',
73
                            	'flags'  	=> FILTER_FORCE_ARRAY,
74
			                   ),
75
		'faxNumber'			=> array(	
76
								'filter'    => FILTER_CALLBACK,
77
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_TELEPHONE',
78
                            	'flags'  	=> FILTER_FORCE_ARRAY,
79
			                   ),
80
		'email'				=> array(	
81
								'filter'    => FILTER_CALLBACK,
82
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_EMAIL',
83
                            	'flags'  	=> FILTER_FORCE_ARRAY,
84
			                   ),
85
		'geoDescription'	=> array(
86
								// a schema:alternateName for schema:GeoCoordinates	
87
								'filter'    => FILTER_CALLBACK,	
88
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_ADDRESS',
89
                            	'flags'  	=> FILTER_FORCE_ARRAY,
90
			                   ),
91
		'lat'				=> array( 
92
								'filter'    => FILTER_CALLBACK,
93
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_LAT_LONG',
94
			                   ),
95
		'long'				=> array( 
96
								'filter'    => FILTER_CALLBACK,
97
		                        'options' 	=> '\BOTK\Filters::FILTER_SANITIZE_LAT_LONG',
98
			                   ),
99
	);
100
101
	public function __construct(array $data = array(), array $customOptions = array()) 
102
    {
103
    	$options = $this->mergeOptions(self::$DEFAULT_OPTIONS,$customOptions);
104
    	parent::__construct($data, $options);
105
	}
106
	
107
	/**
108
	 * Create a normalized address from wollowing datam properties
109
	 * 		'addressCountry',
110
	 * 		'addressLocality',
111
	 * 		'addressRegion',
112
	 * 		'streetAddress',
113
	 * 		'postalCode',
114
	 *  If data is not sufficient to create a good addess, false is returned.
115
	 */	
116
	public function buildNormalizedAddress()
117
	{	
118
		extract($this->data);
119
		
120
		// veryfy that at least a minimum set of information are present
121
		if(empty($streetAddress) || empty($addressCountry) || (empty($addressLocality) && empty($postalCode))){
122
			return false;
123
		}
124
125
		$geolabel = "$streetAddress ,";
126
		if(!empty($postalCode)) { $geolabel.= " $postalCode";}
127
		if(!empty($addressLocality)) { $geolabel.= " $addressLocality"; }
128
		if(!empty($addressRegion)) { $geolabel.= " ($addressRegion)"; }
129
		$geolabel.= " - $addressCountry";
130
		
131
		return \BOTK\Filters::FILTER_SANITIZE_ADDRESS($geolabel);
132
	}
133
	
134
	
135
	public function asTurtle()
136
	{
137
		if(is_null($this->rdf)) {
138
			extract($this->data);
139
140
			// create uris
141
			$organizationUri = $this->getUri();
142
			$addressUri = $organizationUri.'_address';
143
			$placeUri = $organizationUri.'_place';
144
			$geoUri = ( !empty($lat) && !empty($long) )?"geo:$lat,$long":($organizationUri.'_geo'); 
145
		
146
			// define the minimum condition to skipp the rdf generation
147
			$skippAddress = 	empty($alternateName) &&
148
								empty($addressLocality) &&
149
								empty($streetAddress) &&
150
								empty($postalCode) &&
151
								empty($page) &&
152
								empty($telephone) &&
153
								empty($faxNumber) &&
154
								empty($email)
155
			;
156
			$skippGeo = empty($geoDescription) &&
157
						empty($addressLocality) &&
158
						empty($streetAddress) &&
159
						empty($lat) && 
160
						empty($long) ;
161
			$skippPlace = $skippGeo && $skippAddress;
162
			
163
			$skippOrganization = $skippPlace && empty($id)&& empty($vatID) && empty($taxID) && empty($legalName) ;
164
			
165
			// define $_ as a macro to write simple rdf
166
			$tc =0;
167
			$rdf='';
168
			$_= function($format, $var) use(&$lang, &$rdf, &$tc){
169
				if(!is_array($var)) { $var = (array) $var;}
170
				foreach((array)$var as $v){$rdf.= sprintf($format,$v,$lang);$tc++;}
171
			};
172
				
173
	 		// serialize schema:Organization
174
	 		if( !$skippOrganization){
175
	 			$_('<%s> a schema:Organization;', $organizationUri);
176
					!empty($id) 				&& $_('dct:identifier "%s";', $id);
177
					!empty($vatID) 				&& $_('schema:vatID "%s"@%s;', $vatID); 
178
					!empty($taxtID) 			&& $_('schema:taxtID "%s"@%s;', $taxID);
179
					!empty($legalName)			&& $_('schema:legalName """%s"""@%s;', $legalName);
180
					!$skippPlace				&& $_('schema:location <%s>;', $placeUri);
181
				$rdf.=' . ';
182
			}	
183
			
184
			// serialize schema:PostalAddress 
185
			if( !$skippAddress){
186
				$_('<%s> a schema:PostalAddress;', $addressUri);
187
					!empty($businessName) 		&& $_('schema:alternateName """%s"""@%s;', $businessName);
188
					!empty($streetAddress) 		&& $_('schema:streetAddress """%s"""@%s;', $streetAddress);
189
					!empty($postalCode) 		&& $_('schema:postalCode "%s"@%s;', $postalCode);
190
					!empty($addressLocality) 	&& $_('schema:addressLocality """%s"""@%s;', $addressLocality);
191
					!empty($addressRegion) 		&& $_('schema:addressRegion "%s"@%s;', $addressRegion);
192
					!empty($addressCountry) 	&& $_('schema:addressCountry "%s";', $addressCountry);
193
					!empty($telephone) 			&& $_('schema:telephone "%s"@%s;', $telephone);
194
					!empty($faxNumber) 			&& $_('schema:faxNumber "%s"@%s;', $faxNumber);
195
					!empty($page) 				&& $_('schema:page <%s>;', $page);
196
					!empty($email) 				&& $_('schema:email "%s";', $email);
197
				$rdf.=' . ';
198
			}
199
200
			// serialize schema:GeoCoordinates
201 View Code Duplication
			if( !$skippGeo){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
203
				$geoDescription = $this->buildNormalizedAddress();
204
		
205
				$_('<%s> a schema:GeoCoordinates;', $geoUri); 
206
					!empty($geoDescription) 	&& $_('schema:alternateLabel """%s"""@%s;', $geoDescription);
207
					!empty($lat) 				&& $_('wgs:lat %s ;', $lat);
208
					!empty($long) 				&& $_('wgs:long %s ;', $long);
209
				$rdf.=' . ';
210
			}
211
212
			// serialize schema:Place
213 View Code Duplication
			if( !$skippPlace){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
				$_('<%s> a schema:LocalBusiness;', $placeUri);
215
					!empty($businessType) 		&& $_('a %s;', $businessType);
216
					!$skippAddress 				&& $_('schema:address <%s>;', $addressUri);
217
					!$skippGeo 					&& $_('schema:geo <%s>;', $geoUri);
218
				$rdf.=' . ';
219
			}
220
	
221
			$this->rdf = $rdf;
222
			$this->tripleCount  = $tc;
223
		}
224
		
225
		return $this->rdf;
226
	}
227
	
228
}