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){ |
|
|
|
|
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){ |
|
|
|
|
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
|
|
|
} |
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.