Completed
Push — master ( 274d0e...9fc64f )
by mw
34:08
created

tryToFindLocalPropertyDescription()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 15
rs 9.4285
c 1
b 0
f 1
cc 2
eloc 8
nc 2
nop 2
1
<?php
2
3
namespace SMW;
4
5
use RuntimeException;
6
use Onoi\Cache\Cache;
7
use Onoi\Cache\NullCache;
8
9
/**
10
 * This class should be accessed via ApplicationFactory::getPropertySpecificationLookup
11
 * to ensure a singleton instance.
12
 *
13
 * @license GNU GPL v2+
14
 * @since 2.4
15
 *
16
 * @author mwjames
17
 */
18
class PropertySpecificationLookup {
19
20
	/**
21
	 * @var string
22
	 */
23
	const VERSION = '0.1';
24
25
	/**
26
	 * @var Store
27
	 */
28
	private $store;
29
30
	/**
31
	 * @var string
32
	 */
33
	private $languageCode = 'en';
34
35
	/**
36
	 * @var Cache
37
	 */
38
	private $cache;
39
40
	/**
41
	 * @var string
42
	 */
43
	private $cachePrefix = ':smw:pspec:';
44
45
	/**
46
	 * @var integer
47
	 */
48
	private $ttl = 604800; // 7 * 24 * 3600
49
50
	/**
51
	 * @since 2.4
52
	 *
53
	 * @param Store $store
54
	 * @param Cache|null $cache
55
	 */
56
	public function __construct( Store $store, Cache $cache = null ) {
57
		$this->store = $store;
58
		$this->cache = $cache;
59
60
		if ( $this->cache === null ) {
61
			$this->cache = new NullCache();
62
		}
63
	}
64
65
	/**
66
	 * @since 2.4
67
	 */
68
	public function resetCacheFor( DIWikiPage $subject ) {
69
		$this->cache->delete(
70
			$this->cachePrefix . md5( $subject->getHash() . self::VERSION )
71
		);
72
	}
73
74
	/**
75
	 * @since 2.4
76
	 *
77
	 * @param string $cachePrefix
78
	 */
79
	public function setCachePrefix( $cachePrefix ) {
80
		$this->cachePrefix = $cachePrefix . $this->cachePrefix;
81
	}
82
83
	/**
84
	 * @since 2.4
85
	 *
86
	 * @param string
87
	 */
88
	public function getLanguageCode() {
89
		return $this->languageCode;
90
	}
91
92
	/**
93
	 * @since 2.4
94
	 *
95
	 * @param string $languageCode
96
	 */
97
	public function setLanguageCode( $languageCode ) {
98
		$this->languageCode = Localizer::asBCP47FormattedLanguageCode( $languageCode );
99
	}
100
101
	/**
102
	 * We try to cache anything to avoid unnecessary store connections or DB
103
	 * lookups. For cases where a property was changed, the EventDipatcher will
104
	 * receive a 'property.spec.change' event (emitted as soon as the content of
105
	 * a property page was altered) with PropertySpecificationLookup::resetCacheFor
106
	 * being invoked to remove the cache entry for that specific property.
107
	 *
108
	 * @since 2.4
109
	 *
110
	 * @param DIProperty $property
111
	 * @param mixed|null $linker
112
	 *
113
	 * @return string
114
	 */
115
	public function getPropertyDescriptionFor( DIProperty $property, $linker = null ) {
116
117
		$description = array();
118
119
		// Take the linker into account (Special vs. in page rendering etc.)
120
		$key = $this->languageCode . ':' . ( $linker === null ? '-' : '+' );
121
122
		$hash = $this->cachePrefix . md5(
123
			$property->getDiWikiPage()->getHash() . self::VERSION
124
		);
125
126
		if ( $this->cache->contains( $hash ) ) {
127
			$description = $this->cache->fetch( $hash );
128
129
			if ( isset( $description[$key] ) ) {
130
				return trim( $description[$key] );
131
			}
132
		}
133
134
		$description[$key] = $this->tryToFindLocalPropertyDescription( $property, $linker );
135
136
		// If a local property description wasn't available for a predefined property
137
		// the try to find a system translation
138
		if ( trim( $description[$key] ) === '' && !$property->isUserDefined() ) {
139
			$description[$key] = $this->getPredefinedPropertyDescription( $property, $linker );
140
		}
141
142
		$this->cache->save(
143
			$hash,
144
			$description,
145
			$this->ttl
146
		);
147
148
		// Ensure that we return an empty string in case it is just true
149
		return trim( $description[$key] );
150
	}
151
152
	private function getPredefinedPropertyDescription( $property, $linker ) {
153
154
		$description = ' ';
155
		$msgKey = 'smw-pa-property-predefined' . strtolower( $property->getKey() );
156
157
		if ( !wfMessage( $msgKey )->exists() ) {
158
			return $description;
159
		}
160
161
		$message = wfMessage( $msgKey, $property->getLabel() )->inLanguage(
162
			$this->languageCode
163
		);
164
165
		return $linker === null ? $message->escaped() : $message->parse();
166
	}
167
168
	private function tryToFindLocalPropertyDescription( $property, $linker ) {
169
170
		$description = ' ';
171
172
		$dataItems = $this->store->getPropertyValues(
173
			$property->getDiWikiPage(),
174
			new DIProperty( '_PDESC' )
175
		);
176
177
		if ( ( $dataValue = $this->findDataValueByLanguage( $dataItems, $this->languageCode ) ) !== null ) {
178
			$description = $dataValue->getShortWikiText( $linker );
179
		}
180
181
		return $description;
182
	}
183
184
	private function findDataValueByLanguage( $dataItems, $languageCode ) {
185
186
		if ( $dataItems === null || $dataItems === array() ) {
187
			return null;
188
		}
189
190
		foreach ( $dataItems as $dataItem ) {
191
192
			$dataValue = DataValueFactory::getInstance()->newDataItemValue(
193
				$dataItem,
194
				new DIProperty( '_PDESC' )
195
			);
196
197
			// Here a MonolingualTextValue was retunred therefore the method
198
			// can be called without validation
199
			$dv = $dataValue->getTextValueByLanguage( $languageCode );
200
201
			if ( $dv !== null ) {
202
				return $dv;
203
			}
204
		}
205
206
		return null;
207
	}
208
209
}
210