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

AbstractModel::__construct()   C

Complexity

Conditions 8
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 5.7377
c 0
b 0
f 0
cc 8
eloc 14
nc 3
nop 2
1
<?php
2
namespace BOTK\Model;
3
4
use BOTK\Exceptions\DataModelException;
5
6
7
abstract class AbstractModel 
8
{
9
	
10
	/**
11
	 * 
12
	 * MUST be redefined by concrete class with the model schema 
13
	 * Each array element is composed by a propery name and and property options.
14
	 * Property option is an array with following (optional) fields:
15
	 * 		'default' 	a value to be used for the propery
16
	 * 		'filter' 	a php filter 
17
	 * 		'options' 	php filter options
18
	 * 		'flags'		php filter flags
19
	 * 
20
	 * Example:array (
21
	 *	'legalName'			=> array(
22
	 *							'filter'    => FILTER_CALLBACK,	
23
	 *	                        'options' 	=> '\BOTK\Filters::FILTER_NORMALIZZE_ADDRESS',
24
	 *		                   ),
25
	 *	'alternateName'		=> array(		
26
                            	'flags'  	=> FILTER_FORCE_ARRAY,
27
	 * 						),
28
	 * 	'postalCode'		=> array(	// italian rules
29
	 *							'filter'    => FILTER_VALIDATE_REGEXP,	
30
	 *	                        'options' 	=> array('regexp'=>'/^[0-9]{5}$/'),
31
	 *                      	'flags'  	=> FILTER_REQUIRE_SCALAR,
32
	 *		                   ),
33
	 * )
34
	 */
35
	protected static $DEFAULT_OPTIONS  = array(
36
		'base'				=> array(
37
								'default'	=> 'http://linkeddata.center/botk/resource/',
38
								'filter'    => FILTER_SANITIZE_URL,
39
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
40
			                   ),
41
		'uri'				=> array(
42
								'filter'    => FILTER_SANITIZE_URL,
43
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
44
			                   ),
45
		'lang'				=> array(
46
								'default'	=> 'it',		
47
								'filter'    => FILTER_VALIDATE_REGEXP,
48
		                        'options' 	=> array('regexp'=>'/^[a-z]{2}$/'),
49
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
50
			                   ),
51
		'id'				=> array(		
52
								'filter'    => FILTER_VALIDATE_REGEXP,
53
		                        'options' 	=> array('regexp'=>'/^\w+$/'),
54
                            	'flags'  	=> FILTER_REQUIRE_SCALAR,
55
			                   ),
56
	);
57
	
58
	protected $options ;
59
	protected $vocabulary = array(
60
		'botk' 		=> 'http://http://linkeddata.center/botk/v1#',
61
		'schema'	=> 'http://schema.org/',
62
		'wgs' 		=> 'http://www.w3.org/2003/01/geo/wgs84_pos#',
63
		'xsd' 		=> 'http://www.w3.org/2001/XMLSchema#',
64
		'dct' 		=> 'http://purl.org/dc/terms/',
65
		'foaf' 		=> 'http://xmlns.com/foaf/0.1/',
66
	);
67
	protected $data;
68
	protected $rdf =null; //lazy created
69
	protected $tripleCount=0; //lazy created
70
	protected $uniqueIdGenerator=null; // dependency injections
71
	
72
	abstract public function asTurtle();
73
74
	protected function mergeOptions( array $options1, array $options2 )
75
	{
76
    	foreach($options2 as $property=>$option){
77
    		assert(is_array($option));
78
			
79
			$options1[$property]=isset($options1[$property])
80
				?array_merge($options1[$property], $option)
81
				:$option;
82
    	}
83
		
84
		return $options1;
85
	}
86
87
    public function __construct(array $data = array(), array $customOptions = array()) 
88
    {
89
		$options = $this->mergeOptions(self::$DEFAULT_OPTIONS,$customOptions);
90
		
91
		// set default values
92
		foreach( $options as $property=>$option){	
93
			if(empty($data[$property]) && isset($option['default'])){
94
				$data[$property] = $option['default'];
95
			}
96
		}
97
98
		// ensure data are sanitized and validated
99
		$sanitizedData = array_filter( filter_var_array($data, $options), function($value,$property) use($data,$options){
100
			if ($value===false && isset($data[$property]) && $data[$property]!==false){
101
				$id = empty($data['id'])?'unknown':$data['id'];
102
				throw new DataModelException("failed validation of '$property' property of subject with id '$id'. Record dropped.");
103
			}
104
			return !is_null($value);
105
		} , ARRAY_FILTER_USE_BOTH);
106
107
		$this->options = $options;
108
		$this->data = $sanitizedData;
109
		$this->setIdGenerator(function($data){return uniqid();});
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
110
    }
111
112
	
113
	/**
114
	 * dependecy injection setter 
115
	 */
116
	public function setIdGenerator($generator)
117
	{
118
		assert( is_callable($generator));
119
		$this->uniqueIdGenerator = $generator;
120
		
121
		return $this;
122
	}
123
124
125
	/**
126
	 * a generic implementation that use uri, base and id property (all optionals)
127
	 */
128
	public function getUri()
129
	{
130
		if(!empty($this->data['uri'])){
131
			$uri =  $this->data['uri'];
132
		} elseif(!empty($this->data['base'])) {
133
			$idGenerator=$this->uniqueIdGenerator;
134
			$uri = $this->data['base'];
135
			$uri.=empty($this->data['id'])?$idGenerator($this->data):$this->data['id'];
136
		} else{
137
			$idGenerator=$this->uniqueIdGenerator;
138
			$uri = 'urn:local:botk:'.$idGenerator($this->data);
139
		}
140
		
141
		return $uri;
142
	}
143
		
144
145
	public function asArray()
146
	{
147
		return $this->data;
148
	}
149
150
	
151
	public function getOptions()
152
	{
153
		return $this->options;
154
	}
155
156
157
	public function getVocabulary()
158
	{
159
		return $this->vocabulary;
160
	}
161
	
162
	
163
	public function setVocabulary($prefix,$ns)
164
	{
165
		$this->vocabulary[$prefix] = $ns;
166
	}
167
	
168
	
169
	public function unsetVocabulary($prefix)
170
	{
171
		unset($this->vocabulary[$prefix]);
172
	}	
173
	
174
	
175
	public function getTurtleHeader($base=null)
176
	{
177
		$header = empty($base)?'': "@base <$base> .\n";
178
		foreach( $this->vocabulary as $prefix=>$ns ){
179
			$header.="@prefix $prefix: <$ns> .\n";
180
		}
181
		
182
		return $header;
183
	}
184
185
	
186
	public function getTripleCount()
187
	{
188
		// triple count is computed during rdf creation
189
		if (is_null($this->rdf)){
190
			$this->asTurtle();
191
		}
192
		
193
		return $this->tripleCount;
194
	}
195
	
196
		
197
	public function __toString() 
198
	{
199
		return $this->getTurtleHeader() ."\n". $this->asTurtle();
200
	}
201
}