Completed
Push — master ( 3e30e6...aad109 )
by mw
02:31
created

src/DataValueDeserializer.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SEQL;
4
5
use SMW\DataValueFactory;
6
use SMW\DIProperty;
7
use SMW\DIWikiPage;
8
use SMWContainerSemanticData as ContainerSemanticData;
9
use SMWDIContainer as DIContainer;
10
use SMWDITime as DITime;
11
12
/**
13
 * @license GNU GPL v2+
14
 * @since 1.0
15
 *
16
 * @author mwjames
17
 */
18
class DataValueDeserializer {
19
20
	/**
21
	 * @var string
22
	 */
23
	private $querySource;
24
25
	/**
26
	 * @since 1.0
27
	 *
28
	 * @param string $querySource
29
	 */
30 14
	public function __construct( $querySource ) {
31 14
		$this->querySource = $querySource;
32 14
	}
33
34
	/**
35
	 * @since 1.0
36
	 *
37
	 * @return string
38
	 */
39 8
	public function getQuerySource() {
40 8
		return $this->querySource;
41
	}
42
43
	/**
44
	 * @since 1.0
45
	 *
46
	 * @param DIProperty $property
47
	 * @param array|string $value
48
	 *
49
	 * @return DataValue
50
	 */
51 11
	public function newDataValueFrom( DIProperty $property, $value ) {
52
53 11
		$dv = null;
54 11
		$propertyList = array();
55
56 11
		if ( $property->findPropertyTypeId() === '_wpg' || isset( $value['fulltext'] ) ) {
57 2
			$dv = $this->newDataValueFromDataItem( $property, $this->newDiWikiPage( $value ) );
0 ignored issues
show
It seems like $value defined by parameter $value on line 51 can also be of type string; however, SEQL\DataValueDeserializer::newDiWikiPage() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
58 11
		} elseif ( strpos( $property->findPropertyTypeId(), '_rec' ) !== false ) {
59 2
			$dv = $this->newDataValueFromDataItem( $property, $this->newDiContainerOnRecordType( $value, $propertyList ) );
0 ignored issues
show
It seems like $value defined by parameter $value on line 51 can also be of type string; however, SEQL\DataValueDeserializ...ContainerOnRecordType() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
60 2
			$dv->setFieldProperties( $propertyList );
61 10
		} elseif ( $property->findPropertyTypeId() === '_dat' ) {
62 4
			$dv = $this->newDataValueFromDataItem( $property, $this->newDiTime( $value ) );
63 9
		} elseif ( $property->findPropertyTypeId() === '_qty' ) {
64 1
			$dv = $this->newDataValueFromPropertyObject( $property, $value['value'] . ' ' . $value['unit']  );
65 1
		}
66
67 11
		if ( $dv === null ) {
68 4
			$dv = $this->newDataValueFromPropertyObject( $property, $value );
69 4
		}
70
71 11
		return $dv;
72
	}
73
74
	/**
75
	 * @since 1.0
76
	 *
77
	 * @param array $value
78
	 *
79
	 * @return DIWikiPage|false
80
	 */
81 11
	public function newDiWikiPage( array $value ) {
82
83 11
		if ( !isset( $value['namespace'] ) || !isset( $value['fulltext'] ) ) {
84 1
			return false;
85
		}
86
87 10
		$ns = (int)$value['namespace'] === NS_CATEGORY ? NS_CATEGORY : NS_MAIN;
88
89 10
		if ( $ns === NS_CATEGORY ) {
90 1
			$value['fulltext'] = substr( $value['fulltext'], ($pos = strpos( $value['fulltext'], ':') ) !== false ? $pos + 1 : 0 );
91 1
		}
92
93 10
		$title = \Title::newFromText( $this->querySource . ':' . str_replace(" ", "_", $value['fulltext'] ), $ns );
94
95 10
		return DIWikiPage::newFromTitle( $title );
96
	}
97
98 4
	private function newDiTime( $value ) {
99
100 4
		if ( isset( $value['raw'] ) ) {
101 3
			return DITime::doUnserialize( $value['raw'] );
102
		}
103
104
		// < 0.7 API format
105
		// Avoid something like "Part of the date is out of bounds" where the API
106
		// doesn't sent a raw format
107
		// return 9999 BC to indicate that we hit a bounds with the timespamp
108
		try{
109 1
			$dataItem = DITime::newFromTimestamp( $value );
110 1
		} catch ( \Exception $e ) {
111
			$dataItem = DITime::doUnserialize( '2/-9999' );
112
		}
113
114 1
		return $dataItem;
115
	}
116
117 5
	private function newDataValueFromPropertyObject( $property, $value ) {
118
119
		try{
120 5
			$dv = DataValueFactory::newPropertyObjectValue( $property, $value );
121 5
		} catch ( \Exception $e ) {
122
			$dv = false;
123
		}
124
125 5
		return $dv;
126
	}
127
128 7
	private function newDataValueFromDataItem( $property, $dataItem = false ) {
129
130 7
		if ( $dataItem === false ) {
131 1
			return false;
132
		}
133
134
		try{
135 6
			$dv = DataValueFactory::newDataItemValue( $dataItem, $property );
136 6
		} catch ( \Exception $e ) {
137
			$dv = false;
138
		}
139
140 6
		return $dv;
141
	}
142
143 2
	private function newDiContainerOnRecordType( array $value, &$propertyList ) {
144
145
		// Remote container to use an anonymous
146 2
		$semanticData = ContainerSemanticData::makeAnonymousContainer();
147
148 2
		foreach ( $value as $recValue ) {
149 2
			$recordProperty = DIProperty::newFromUserLabel( $recValue['label'] );
150 2
			$recordProperty->setInterwiki( $this->querySource );
151 2
			$recordProperty->setPropertyTypeId( $recValue['typeid'] );
152 2
			$propertyList[] = $recordProperty;
153
154 2
			foreach ( $recValue['item'] as $item ) {
155 2
				$dataValue = $this->newDataValueFrom( $recordProperty, $item );
156
157 2
				if ( $dataValue === false ) {
158
					continue;
159
				}
160
161 2
				$semanticData->addPropertyObjectValue( $recordProperty, $dataValue->getDataItem() );
162 2
			}
163 2
		}
164
165 2
		return new DIContainer( $semanticData );
166
	}
167
168
}
169